Compare commits
361 Commits
v1.4.2
...
issue-1973
| Author | SHA1 | Date | |
|---|---|---|---|
| 5b8793155c | |||
| 276ee537e1 | |||
| 7e628ad1a1 | |||
| 0a40b53412 | |||
| 682f90de2f | |||
| 1a07ab8ab1 | |||
| d86449a8ea | |||
| 75d2e540aa | |||
| e73612b4d2 | |||
| a19aec9d9f | |||
| 61be1d8b0a | |||
| 4483533417 | |||
| fb703cd856 | |||
| c0ff7572ac | |||
| 8e7ffc8ddb | |||
| f994abee21 | |||
| 6f1dfb6848 | |||
| 306bc7abc3 | |||
| 8ed48183c7 | |||
| fdc3fe1a8d | |||
| 2805770510 | |||
| 03052baabe | |||
| 23e643c686 | |||
| faeae086d1 | |||
| 38e64fafbd | |||
| e723c245ee | |||
| 3e57dacfd3 | |||
| f5accc8464 | |||
| 238fe17df0 | |||
| 295befbaaa | |||
| 5f20033f18 | |||
| 5f376c6e21 | |||
| 68a99c5410 | |||
| 8db70ee7a5 | |||
| b6155afd32 | |||
| d5bf9f20a6 | |||
| 2d5c0fda4a | |||
| 5d56001826 | |||
| 2de91f9a3a | |||
| e06e6bd483 | |||
| 1e57e85382 | |||
| ca03406a3d | |||
| 2d28da9b0e | |||
| edb1717969 | |||
| 1b51234edc | |||
| e6d896d91e | |||
| a989fa7e64 | |||
| f7002c7fad | |||
| 41d986bdca | |||
| 192a8116f1 | |||
| 173d85bf84 | |||
| b310e92d7a | |||
| 4a92ee07cc | |||
| fdffe20c46 | |||
| 15d464d620 | |||
| 1bd4526e4c | |||
| 816308e3ca | |||
| cfd851a980 | |||
| d129be7e86 | |||
| 6433fcef72 | |||
| d120556772 | |||
| 19f40b8549 | |||
| 89acf73010 | |||
| b70276d896 | |||
| 76b370e249 | |||
| b73f2ef0b9 | |||
| 762c2d70bd | |||
| 4e81bdd76f | |||
| 4d87b447a6 | |||
| 8f0d0e4f4d | |||
| c39a696977 | |||
| b78a0257b4 | |||
| cdede7eca4 | |||
| 72180164d8 | |||
| 2dc0db230c | |||
| 24657f6b3c | |||
| e358476c71 | |||
| 45a637f33b | |||
| 76cf9596e2 | |||
| 95c07a4e76 | |||
| 2d1d5a419c | |||
| f45547e2c1 | |||
| 1f463c7152 | |||
| 2c92c6b0a6 | |||
| f83ee45ac8 | |||
| f695fafe74 | |||
| f6ab105ef7 | |||
| f81a2c4ebb | |||
| c602b3d967 | |||
| f213082da5 | |||
| 8d26fa2a89 | |||
| a06231d007 | |||
| 68b84ea786 | |||
| 868e99e0b5 | |||
| 95db98e574 | |||
| 63fc7e05b6 | |||
| 2c2bb64c09 | |||
| 0f5d07c6b1 | |||
| fbb6aa580e | |||
| d9692a4f5f | |||
| ef0c09ca5b | |||
| 752c61ae71 | |||
| 8f635076ea | |||
| 8d5130a329 | |||
| 09a5e0893b | |||
| de8c315a7a | |||
| 3abdd40498 | |||
| 5b7ebec7e3 | |||
| de603ef909 | |||
| a0a6779097 | |||
| ce9645864d | |||
| d076c4e73d | |||
| 3e4c6a9c51 | |||
| 74a2d7d5e7 | |||
| 219f9ebede | |||
| ba0e918fef | |||
| 9b75a4f199 | |||
| 2d65594383 | |||
| 36f439a82b | |||
| 0efc99e43e | |||
| c0c35f32a8 | |||
| 53e51c76a5 | |||
| 14265a7b70 | |||
| 4467f9118f | |||
| 240a903438 | |||
| afa331e8fc | |||
| 6620e650ef | |||
| 2aa7438346 | |||
| 26fb7f33fb | |||
| 6f4451364b | |||
| 1a642108ef | |||
| dddb7b2878 | |||
| 82cafe6e94 | |||
| b578479270 | |||
| 85b77cd3c0 | |||
| 38c3f8bf9a | |||
| f558203a9d | |||
| 347d6e2c2e | |||
| eb4d540b04 | |||
| 83b6ffbba9 | |||
| 50c5f0874f | |||
| a72e6aeafe | |||
| 683cd76cc5 | |||
| df313dbfec | |||
| 2e3579a8fd | |||
| 99c8ceae9a | |||
| fa67f4fef7 | |||
| e9a7ccd00c | |||
| 76e5824d99 | |||
| 3bf101d7ac | |||
| c28320e1b2 | |||
| ea5b66d463 | |||
| 8a67c39279 | |||
| 67054bda3d | |||
| ed4c5a3a17 | |||
| ae1b1ce99e | |||
| 5d3c96ead2 | |||
| 63ad7fb128 | |||
| ccdbb1d62c | |||
| 3474f0da04 | |||
| 0fd9a9df29 | |||
| e29011eb95 | |||
| f52d2814df | |||
| 6e507f0cdc | |||
| f825901849 | |||
| 5aaceee978 | |||
| f53dbbfebf | |||
| d29263ef57 | |||
| d8c8fb4e18 | |||
| 835f9fb5e0 | |||
| ecbcbbe8d4 | |||
| 37b1bff8f2 | |||
| 5e8f9b900f | |||
| ddefead764 | |||
| 54f83cee1c | |||
| 7f3bd8c668 | |||
| ea10f2af47 | |||
| 2d810a2864 | |||
| bac2386a1a | |||
| 06ec12ba17 | |||
| 7f713e5592 | |||
| ee2556ecb6 | |||
| e57787393e | |||
| b7634024d6 | |||
| 9417671606 | |||
| 2e652b4219 | |||
| 1d6ebed7e5 | |||
| 19cf22b9e3 | |||
| 75fbdd3ac4 | |||
| 13e317d927 | |||
| 7a309ca367 | |||
| a992c93198 | |||
| ee3a653c1b | |||
| e8e7028792 | |||
| 2403d32ae4 | |||
| 1c89c7290c | |||
| 1891f6fd7e | |||
| e933b41236 | |||
| 9f7432134c | |||
| 7d69e5aaab | |||
| 780b1a0d53 | |||
| ea37f3e9f7 | |||
| c6ed117df6 | |||
| cedcc29e01 | |||
| d5219e7f0c | |||
| 9a6dec0dbd | |||
| 17574ee554 | |||
| 926f4e497a | |||
| acbe94df27 | |||
| a2f018a00b | |||
| 98cc1b1022 | |||
| 745f46f81f | |||
| 6912ed40b4 | |||
| a89dbc1152 | |||
| 0c4d46ead5 | |||
| eae9bac938 | |||
| cb91c8c41c | |||
| cb1f3e9843 | |||
| d4927db52b | |||
| bc7300bd01 | |||
| 278d7fa3f9 | |||
| d9af91bc4d | |||
| 18fe9f305c | |||
| e5e64365fc | |||
| fdf170529f | |||
| 50283ab543 | |||
| 3fa3e5acec | |||
| 4230cd5b5a | |||
| 1ad6527de5 | |||
| 0421ad80c1 | |||
| 35e0201f06 | |||
| 118eea5e77 | |||
| 7f317be325 | |||
| e1aa9f6de4 | |||
| 058a5e3bb2 | |||
| 92b49ec2b5 | |||
| 583a04b092 | |||
| 444a04e2f7 | |||
| 157e702ffd | |||
| 77892f41ec | |||
| 6ba0e1dbf6 | |||
| 950fbbaa83 | |||
| 912c431511 | |||
| 5d6b82724a | |||
| 78c976ad4f | |||
| fbdfd135da | |||
| dd51783d9e | |||
| 158fc2fca3 | |||
| 24284a6f3a | |||
| 85c2c63aa3 | |||
| f354f7de63 | |||
| 540c0a8100 | |||
| 4d00fede56 | |||
| b1bc5c08ff | |||
| 305d4f4fe5 | |||
| 2d149e9a5d | |||
| 87b9ff3c35 | |||
| 1c36b3c74c | |||
| 068e4b8e3d | |||
| df38a6424f | |||
| 5d186e56a5 | |||
| 0fafcfa006 | |||
| e3fdbafd86 | |||
| 07c2b14479 | |||
| cdc844aaf3 | |||
| e1b7d361b9 | |||
| 12ef29bebc | |||
| 22ed241d50 | |||
| 28e5a3c5be | |||
| bb4d88cc68 | |||
| 4aaea2b93f | |||
| bc8d7c4fc3 | |||
| 5ea6c46778 | |||
| b28f8ba85b | |||
| 4db50fb749 | |||
| 1dd0c90a04 | |||
| 2bace2bde2 | |||
| 1a9cb832ab | |||
| 6844a46c93 | |||
| e9e45707da | |||
| b9d02ff4c4 | |||
| 29b64300bc | |||
| 777355e86e | |||
| 620a177ce8 | |||
| 683c2dfbeb | |||
| 266cbcc6f4 | |||
| 8a45602ae6 | |||
| 711419a797 | |||
| 603f3057eb | |||
| fa6fc1f871 | |||
| 49fa320989 | |||
| 2f301bf150 | |||
| b4892ce17f | |||
| 151c171616 | |||
| 79477a2de3 | |||
| 78aadda931 | |||
| b50706505f | |||
| 9114821fb1 | |||
| 1195582da8 | |||
| 258987b0ff | |||
| a6a734c70d | |||
| d6c23a2a9b | |||
| db028904d7 | |||
| 63a571306c | |||
| bc4db61e25 | |||
| c7e6e28830 | |||
| 1d7b6fdb2c | |||
| ce5d8eeff8 | |||
| 894e0e6132 | |||
| 127f0ecf3f | |||
| cf7767e702 | |||
| e0aedc7949 | |||
| bad78de74c | |||
| 12df8a169f | |||
| 15c9d33339 | |||
| 7e0fafbaf1 | |||
| 57b9c1dd7a | |||
| 8ba0c17259 | |||
| cd32151083 | |||
| 75b52d672e | |||
| 11d04508f7 | |||
| e641b773b5 | |||
| 6e5899c654 | |||
| c66ffaa7f9 | |||
| 5193c6a5d8 | |||
| e7212af547 | |||
| 3ca1357af4 | |||
| 90e95213e4 | |||
| ae2d4da585 | |||
| 691d5cd1e6 | |||
| 58a46c6417 | |||
| d3f6160e62 | |||
| 03e4afb12f | |||
| 6802f6028e | |||
| 5ca61cfe18 | |||
| 32d55b48f2 | |||
| ab4b6f9e54 | |||
| 9100ad1220 | |||
| 8b4f8fb572 | |||
| 87e0e5bf16 | |||
| e4c2d6cf6e | |||
| fb0bdb5112 | |||
| f4b3645435 | |||
| c27f2badf7 | |||
| 1a877d6535 | |||
| 5ada9331b6 | |||
| a0f4ccb7a4 | |||
| 5b5524a7dd | |||
| 3cc464c9c9 | |||
| 51555667cf | |||
| e01ea7010f | |||
| 77732c83c9 | |||
| a67fc83949 | |||
| 3d920725aa | |||
| 2f2fbea558 | |||
| e7a86a2960 | |||
| b282d97ffe | |||
| e4ca52a95f | |||
| d972d9ec74 | |||
| 0721a6b050 | |||
| 762ee6550e |
+13
-1
@@ -7,11 +7,23 @@ insert_final_newline = true
|
|||||||
|
|
||||||
indent_style = tab
|
indent_style = tab
|
||||||
tab_width = 4
|
tab_width = 4
|
||||||
continuation_indent_size = 8 #IntelliJ Idea specific workaround
|
|
||||||
|
|
||||||
charset = utf-8
|
charset = utf-8
|
||||||
trim_trailing_whitespace = true
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
|
[*.java]
|
||||||
|
ij_java_continuation_indent_size = 8
|
||||||
|
ij_java_use_single_class_imports = true
|
||||||
|
ij_java_class_count_to_use_import_on_demand = 99
|
||||||
|
ij_java_names_count_to_use_import_on_demand = 99
|
||||||
|
ij_java_packages_to_use_import_on_demand = *
|
||||||
|
|
||||||
|
[*.kt]
|
||||||
|
ij_kotlin_continuation_indent_size = 8
|
||||||
|
ij_kotlin_name_count_to_use_star_import = 99
|
||||||
|
ij_kotlin_name_count_to_use_star_import_for_members = 99
|
||||||
|
ij_kotlin_packages_to_use_import_on_demand = *
|
||||||
|
|
||||||
[*.yml]
|
[*.yml]
|
||||||
indent_style = space
|
indent_style = space
|
||||||
indent_size = 2
|
indent_size = 2
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
* text=auto eol=lf
|
||||||
|
|
||||||
|
*.java text eol=lf diff=java
|
||||||
|
*.kt text eol=lf diff=kotlin
|
||||||
|
*.kts text eol=lf diff=kotlin
|
||||||
|
|
||||||
|
gradlew text eol=lf
|
||||||
|
|
||||||
|
*.bat text eol=crlf
|
||||||
|
|
||||||
|
*.png binary
|
||||||
|
*.jar binary
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
blank_issues_enabled: false
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
---
|
|
||||||
name: Decompilation error
|
|
||||||
about: Create a report to help us improve jadx decompiler
|
|
||||||
title: "[core]"
|
|
||||||
labels: Core, bug
|
|
||||||
assignees: ''
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Checks before report**
|
|
||||||
- check [Troubleshooting Q&A](https://github.com/skylot/jadx/wiki/Troubleshooting-Q&A) section on wiki
|
|
||||||
- search existing issues by exception message
|
|
||||||
|
|
||||||
**Describe error**
|
|
||||||
- full name of method or class with error
|
|
||||||
- full java stacktrace (no need to copy method fallback code (commented pseudocode))
|
|
||||||
- **IMPORTANT!** attach or provide link to apk file (double check apk version)
|
|
||||||
|
|
||||||
**Note**: GitHub don't allow attach files with `.apk` extension, but you can change extension by adding `.zip` at the end :)
|
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
name: Decompilation issue
|
||||||
|
description: Create a report to help us improve jadx decompiler
|
||||||
|
title: '[core] '
|
||||||
|
labels:
|
||||||
|
- Core
|
||||||
|
- bug
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
**Checks before submit**
|
||||||
|
- check [Troubleshooting Q&A](https://github.com/skylot/jadx/wiki/Troubleshooting-Q&A) section on wiki
|
||||||
|
- try [latest unstable build](https://nightly.link/skylot/jadx/workflows/build-artifacts/master), maybe issue already fixed
|
||||||
|
- search existing issues by exception message
|
||||||
|
- type: textarea
|
||||||
|
id: details
|
||||||
|
attributes:
|
||||||
|
label: Issue details
|
||||||
|
placeholder: >-
|
||||||
|
Describe issue
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: logs
|
||||||
|
attributes:
|
||||||
|
label: Relevant log output or stacktrace
|
||||||
|
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
|
||||||
|
render: java
|
||||||
|
- type: textarea
|
||||||
|
id: sample
|
||||||
|
attributes:
|
||||||
|
label: Provide sample and class/method full name
|
||||||
|
description: |
|
||||||
|
- sample: attach or provide a link
|
||||||
|
- full name of class or method with issue
|
||||||
|
- other details which may help to reproduce issue
|
||||||
|
- type: input
|
||||||
|
id: jadx-version
|
||||||
|
attributes:
|
||||||
|
label: Jadx version
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
---
|
|
||||||
name: Feature Request
|
|
||||||
about: Suggest an idea for jadx
|
|
||||||
title: "[feature]"
|
|
||||||
labels: new feature
|
|
||||||
assignees: ''
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
*Describe your idea:*
|
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
name: Feature Request
|
||||||
|
description: Suggest an idea for jadx
|
||||||
|
title: '[feature] '
|
||||||
|
labels:
|
||||||
|
- 'new feature'
|
||||||
|
body:
|
||||||
|
- type: textarea
|
||||||
|
id: details
|
||||||
|
attributes:
|
||||||
|
label: Describe your idea
|
||||||
|
placeholder: Feature details
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
name: jadx-gui issue
|
||||||
|
description: Create a bug report about issue found in jadx-gui
|
||||||
|
title: '[gui] '
|
||||||
|
labels:
|
||||||
|
- GUI
|
||||||
|
- bug
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
**Checks before submit**
|
||||||
|
- check [Troubleshooting Q&A](https://github.com/skylot/jadx/wiki/Troubleshooting-Q&A) section on wiki
|
||||||
|
- try [latest unstable build](https://nightly.link/skylot/jadx/workflows/build-artifacts/master), maybe issue already fixed
|
||||||
|
- search existing issues by exception message
|
||||||
|
- type: textarea
|
||||||
|
id: details
|
||||||
|
attributes:
|
||||||
|
label: Issue details
|
||||||
|
placeholder: Describe issue and how to reproduce it
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: input
|
||||||
|
id: jadx-version
|
||||||
|
attributes:
|
||||||
|
label: Jadx version
|
||||||
|
placeholder: check `Help->About`
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: input
|
||||||
|
id: java-version
|
||||||
|
attributes:
|
||||||
|
label: Java version
|
||||||
|
placeholder: check `Help->About`
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: checkboxes
|
||||||
|
id: os
|
||||||
|
attributes:
|
||||||
|
label: OS
|
||||||
|
options:
|
||||||
|
- label: Windows
|
||||||
|
- label: Linux
|
||||||
|
- label: macOS
|
||||||
@@ -8,15 +8,15 @@ jobs:
|
|||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Set up JDK
|
- name: Set up JDK
|
||||||
uses: actions/setup-java@v3
|
uses: actions/setup-java@v4
|
||||||
with:
|
with:
|
||||||
distribution: 'adopt'
|
distribution: temurin
|
||||||
java-version: 8
|
java-version: 11
|
||||||
|
|
||||||
- name: Set jadx version
|
- name: Set jadx version
|
||||||
run: |
|
run: |
|
||||||
@@ -24,15 +24,13 @@ jobs:
|
|||||||
JADX_VERSION="${JADX_LAST_TAG:1}.$GITHUB_RUN_NUMBER-${GITHUB_SHA:0:8}"
|
JADX_VERSION="${JADX_LAST_TAG:1}.$GITHUB_RUN_NUMBER-${GITHUB_SHA:0:8}"
|
||||||
echo "JADX_VERSION=$JADX_VERSION" >> $GITHUB_ENV
|
echo "JADX_VERSION=$JADX_VERSION" >> $GITHUB_ENV
|
||||||
|
|
||||||
- uses: burrunan/gradle-cache-action@v1
|
- name: Build with Gradle
|
||||||
name: Build with Gradle
|
uses: gradle/actions/setup-gradle@v3
|
||||||
env:
|
|
||||||
TERM: dumb
|
|
||||||
with:
|
with:
|
||||||
arguments: clean dist copyExe
|
arguments: dist copyExe
|
||||||
|
|
||||||
- name: Save bundle artifact
|
- name: Save bundle artifact
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: ${{ format('jadx-{0}', env.JADX_VERSION) }}
|
name: ${{ format('jadx-{0}', env.JADX_VERSION) }}
|
||||||
# Waiting fix for https://github.com/actions/upload-artifact/issues/39 to upload zip file
|
# Waiting fix for https://github.com/actions/upload-artifact/issues/39 to upload zip file
|
||||||
@@ -42,7 +40,7 @@ jobs:
|
|||||||
retention-days: 30
|
retention-days: 30
|
||||||
|
|
||||||
- name: Save exe artifact
|
- name: Save exe artifact
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: ${{ format('jadx-gui-{0}-no-jre-win.exe', env.JADX_VERSION) }}
|
name: ${{ format('jadx-gui-{0}-no-jre-win.exe', env.JADX_VERSION) }}
|
||||||
path: build/*.exe
|
path: build/*.exe
|
||||||
@@ -52,12 +50,14 @@ jobs:
|
|||||||
build-win-bundle:
|
build-win-bundle:
|
||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Set up JDK
|
- name: Set up JDK
|
||||||
uses: oracle-actions/setup-java@v1 # set latest java version by default
|
uses: oracle-actions/setup-java@v1
|
||||||
|
with:
|
||||||
|
release: 17
|
||||||
|
|
||||||
- name: Print Java version
|
- name: Print Java version
|
||||||
shell: bash
|
shell: bash
|
||||||
@@ -70,15 +70,13 @@ jobs:
|
|||||||
JADX_VERSION="${JADX_LAST_TAG:1}.$GITHUB_RUN_NUMBER-${GITHUB_SHA:0:8}"
|
JADX_VERSION="${JADX_LAST_TAG:1}.$GITHUB_RUN_NUMBER-${GITHUB_SHA:0:8}"
|
||||||
echo "JADX_VERSION=$JADX_VERSION" >> $GITHUB_ENV
|
echo "JADX_VERSION=$JADX_VERSION" >> $GITHUB_ENV
|
||||||
|
|
||||||
- uses: gradle/gradle-build-action@v2
|
- name: Build with Gradle
|
||||||
name: Build with Gradle
|
uses: gradle/actions/setup-gradle@v3
|
||||||
env:
|
|
||||||
TERM: dumb
|
|
||||||
with:
|
with:
|
||||||
arguments: clean dist -PbundleJRE=true
|
arguments: dist -PbundleJRE=true
|
||||||
|
|
||||||
- name: Save exe bundle artifact
|
- name: Save exe bundle artifact
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: ${{ format('jadx-gui-{0}-with-jre-win', env.JADX_VERSION) }}
|
name: ${{ format('jadx-gui-{0}-with-jre-win', env.JADX_VERSION) }}
|
||||||
path: jadx-gui/build/*-with-jre-win/*
|
path: jadx-gui/build/*-with-jre-win/*
|
||||||
|
|||||||
@@ -8,21 +8,21 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
tests:
|
tests:
|
||||||
runs-on: ubuntu-latest
|
strategy:
|
||||||
|
matrix:
|
||||||
|
os: [ ubuntu-latest, windows-latest ]
|
||||||
|
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Set up JDK
|
- name: Set up JDK
|
||||||
uses: actions/setup-java@v3
|
uses: actions/setup-java@v4
|
||||||
with:
|
with:
|
||||||
distribution: 'adopt'
|
distribution: temurin
|
||||||
java-version: 8
|
java-version: 11
|
||||||
|
|
||||||
- uses: burrunan/gradle-cache-action@v1
|
- name: Build with Gradle
|
||||||
name: Build with Gradle
|
uses: gradle/actions/setup-gradle@v3
|
||||||
env:
|
|
||||||
TERM: dumb
|
|
||||||
with:
|
with:
|
||||||
arguments: clean build dist copyExe --warning-mode=all
|
arguments: build dist copyExe
|
||||||
|
|||||||
@@ -25,10 +25,10 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Initialize CodeQL
|
- name: Initialize CodeQL
|
||||||
uses: github/codeql-action/init@v2
|
uses: github/codeql-action/init@v3
|
||||||
with:
|
with:
|
||||||
queries: +security-extended
|
queries: +security-extended
|
||||||
languages: ${{ matrix.language }}
|
languages: ${{ matrix.language }}
|
||||||
@@ -38,4 +38,4 @@ jobs:
|
|||||||
./gradlew clean build -x checkstyleTest -x checkstyleMain -x test -x ':jadx-core:testClasses'
|
./gradlew clean build -x checkstyleTest -x checkstyleMain -x test -x ':jadx-core:testClasses'
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
- name: Perform CodeQL Analysis
|
||||||
uses: github/codeql-action/analyze@v2
|
uses: github/codeql-action/analyze@v3
|
||||||
|
|||||||
@@ -1,10 +1,15 @@
|
|||||||
name: "Validate Gradle Wrapper"
|
name: Validate Gradle Wrapper
|
||||||
on: [push]
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ master, build-test ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ master ]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
validation:
|
validation:
|
||||||
name: "Validation"
|
name: Validation
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
- uses: gradle/wrapper-validation-action@v1
|
- uses: gradle/wrapper-validation-action@v1
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ classes/
|
|||||||
idea/
|
idea/
|
||||||
.gradle/
|
.gradle/
|
||||||
node_modules/
|
node_modules/
|
||||||
|
.vscode/
|
||||||
|
|
||||||
jadx-output/
|
jadx-output/
|
||||||
*-tmp/
|
*-tmp/
|
||||||
|
|||||||
+10
-10
@@ -8,17 +8,17 @@ before_script:
|
|||||||
stages:
|
stages:
|
||||||
- test
|
- test
|
||||||
|
|
||||||
java-8:
|
|
||||||
stage: test
|
|
||||||
image: openjdk:8
|
|
||||||
script: ./gradlew clean build dist copyExe --warning-mode=all
|
|
||||||
|
|
||||||
java-11:
|
java-11:
|
||||||
stage: test
|
stage: test
|
||||||
image: openjdk:11
|
image: eclipse-temurin:11
|
||||||
script: ./gradlew clean build dist copyExe --warning-mode=all
|
script: ./gradlew clean build dist copyExe
|
||||||
|
|
||||||
java-latest:
|
java-17:
|
||||||
stage: test
|
stage: test
|
||||||
image: openjdk:latest
|
image: eclipse-temurin:17
|
||||||
script: java -version && ./gradlew clean build dist --warning-mode=all
|
script: ./gradlew clean build dist copyExe
|
||||||
|
|
||||||
|
java-21:
|
||||||
|
stage: test
|
||||||
|
image: eclipse-temurin:21
|
||||||
|
script: ./gradlew clean build dist copyExe
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="jadx-gui" type="Application" factoryName="Application">
|
||||||
|
<option name="MAIN_CLASS_NAME" value="jadx.gui.JadxGUI"/>
|
||||||
|
<module name="jadx.jadx-gui.main"/>
|
||||||
|
<option name="PROGRAM_PARAMETERS" value="-v"/>
|
||||||
|
<option name="VM_PARAMETERS"
|
||||||
|
value="-Xms128M -XX:MaxRAMPercentage=70.0 -Dawt.useSystemAAFontSettings=lcd -Dswing.aatext=true -Djava.util.Arrays.useLegacyMergeSort=true -Djdk.util.zip.disableZip64ExtraFieldValidation=true -XX:+IgnoreUnrecognizedVMOptions --add-opens=java.base/java.lang=ALL-UNNAMED"/>
|
||||||
|
<method v="2">
|
||||||
|
<option name="Make" enabled="true"/>
|
||||||
|
</method>
|
||||||
|
</configuration>
|
||||||
|
</component>
|
||||||
+20
@@ -0,0 +1,20 @@
|
|||||||
|
# Config for 'typos' spellchecker (https://github.com/crate-ci/typos)
|
||||||
|
|
||||||
|
[default.extend-words]
|
||||||
|
IPUT = "IPUT"
|
||||||
|
Laf = "Laf"
|
||||||
|
Darcula="Darcula"
|
||||||
|
|
||||||
|
[default]
|
||||||
|
extend-ignore-identifiers-re = [
|
||||||
|
"finaly", # intentional package name
|
||||||
|
]
|
||||||
|
|
||||||
|
[files]
|
||||||
|
extend-exclude = [
|
||||||
|
"config/",
|
||||||
|
"jadx-core/src/main/resources/",
|
||||||
|
"jadx-core/src/test/",
|
||||||
|
"jadx-gui/src/main/resources/i18n/",
|
||||||
|
"!jadx-gui/src/main/resources/i18n/Messages_en_US.properties",
|
||||||
|
]
|
||||||
+7
-12
@@ -1,32 +1,27 @@
|
|||||||
# Contributing
|
# Contributing
|
||||||
|
|
||||||
Please note we have a [code of conduct](CODE_OF_CONDUCT.md), please follow it in all your interactions with the project.
|
Please note, we have [code of conduct](CODE_OF_CONDUCT.md), please follow it in all your interactions with the project.
|
||||||
|
|
||||||
## Open Issue
|
## Open Issue
|
||||||
|
|
||||||
1. Before proceed please do:
|
1. Before proceed, please do:
|
||||||
- check [Troubleshooting Q&A](https://github.com/skylot/jadx/wiki/Troubleshooting-Q&A) section on wiki
|
- check [Troubleshooting Q&A](https://github.com/skylot/jadx/wiki/Troubleshooting-Q&A) section on wiki
|
||||||
- search existing issues by exception message
|
- search existing issues by exception message
|
||||||
|
|
||||||
2. Describe error
|
2. Describe error:
|
||||||
**Describe error**
|
|
||||||
- full name of method or class with error
|
- full name of method or class with error
|
||||||
- full java stacktrace (no need to copy method fallback code (commented pseudocode))
|
- full java stacktrace (no need to copy method fallback code (commented pseudocode))
|
||||||
- **IMPORTANT!:** attach or provide link to apk file (double check apk version)
|
- **IMPORTANT!:** attach or provide link to apk file (double check apk version)
|
||||||
|
|
||||||
**Note**: GitHub don't allow attach files with `.apk` extension, but you can change extension by adding `.zip` at the end :)
|
**Note**: GitHub don't allow attaching files with `.apk` extension, but you can change extension by adding `.zip` at the end :)
|
||||||
|
|
||||||
|
|
||||||
## Pull Request Process
|
## Pull Request Process
|
||||||
|
|
||||||
1. Please don't submit any code style fixes, dependencies updates or other changes which are not fixing any issues.
|
1. Please don't submit any code style fixes or dependencies updates changes.
|
||||||
|
|
||||||
1. Before start working on PR please discuss the change you wish to make via issue. PR without corresponding issue will be rejected.
|
1. Use only features and API from Java 11 or below.
|
||||||
|
|
||||||
1. Use only features and API from Java 8 or below.
|
|
||||||
|
|
||||||
1. If possible don't add additional dependencies especially if they are big.
|
|
||||||
|
|
||||||
1. Make sure your code is correctly formatted, see description here: [Code Formatting](https://github.com/skylot/jadx/wiki/Code-Formatting).
|
1. Make sure your code is correctly formatted, see description here: [Code Formatting](https://github.com/skylot/jadx/wiki/Code-Formatting).
|
||||||
|
|
||||||
1. Make sure your changes is passing build: `./gradlew clean build dist`
|
1. Make sure your changes are passing build: `./gradlew clean build dist`
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
## JADX
|
## JADX
|
||||||
|
|
||||||
[](https://github.com/skylot/jadx/actions?query=workflow%3ABuild)
|

|
||||||

|

|
||||||

|

|
||||||

|

|
||||||
@@ -48,7 +48,7 @@ On Windows run `.bat` files with double-click\
|
|||||||
For Windows, you can download it from [oracle.com](https://www.oracle.com/java/technologies/downloads/#jdk17-windows) (select x64 Installer).
|
For Windows, you can download it from [oracle.com](https://www.oracle.com/java/technologies/downloads/#jdk17-windows) (select x64 Installer).
|
||||||
|
|
||||||
### Install
|
### Install
|
||||||
1. Arch linux 
|
1. Arch linux 
|
||||||
```bash
|
```bash
|
||||||
sudo pacman -S jadx
|
sudo pacman -S jadx
|
||||||
```
|
```
|
||||||
@@ -65,7 +65,7 @@ For Windows, you can download it from [oracle.com](https://www.oracle.com/java/t
|
|||||||
You can use jadx in your java projects, check details on [wiki page](https://github.com/skylot/jadx/wiki/Use-jadx-as-a-library)
|
You can use jadx in your java projects, check details on [wiki page](https://github.com/skylot/jadx/wiki/Use-jadx-as-a-library)
|
||||||
|
|
||||||
### Build from source
|
### Build from source
|
||||||
JDK 8 or higher must be installed:
|
JDK 11 or higher must be installed:
|
||||||
```
|
```
|
||||||
git clone https://github.com/skylot/jadx.git
|
git clone https://github.com/skylot/jadx.git
|
||||||
cd jadx
|
cd jadx
|
||||||
@@ -79,7 +79,10 @@ and also packed to `build/jadx-<version>.zip`
|
|||||||
|
|
||||||
### Usage
|
### Usage
|
||||||
```
|
```
|
||||||
jadx[-gui] [options] <input files> (.apk, .dex, .jar, .class, .smali, .zip, .aar, .arsc, .aab)
|
jadx[-gui] [command] [options] <input files> (.apk, .dex, .jar, .class, .smali, .zip, .aar, .arsc, .aab, .xapk)
|
||||||
|
commands (use '<command> --help' for command options):
|
||||||
|
plugins - manage jadx plugins
|
||||||
|
|
||||||
options:
|
options:
|
||||||
-d, --output-dir - output directory
|
-d, --output-dir - output directory
|
||||||
-ds, --output-dir-src - output directory for sources
|
-ds, --output-dir-src - output directory for sources
|
||||||
@@ -97,25 +100,39 @@ options:
|
|||||||
'simple' - simplified instructions (linear, with goto's)
|
'simple' - simplified instructions (linear, with goto's)
|
||||||
'fallback' - raw instructions without modifications
|
'fallback' - raw instructions without modifications
|
||||||
--show-bad-code - show inconsistent code (incorrectly decompiled)
|
--show-bad-code - show inconsistent code (incorrectly decompiled)
|
||||||
|
--no-xml-pretty-print - do not prettify XML
|
||||||
--no-imports - disable use of imports, always write entire package name
|
--no-imports - disable use of imports, always write entire package name
|
||||||
--no-debug-info - disable debug info
|
--no-debug-info - disable debug info parsing and processing
|
||||||
--add-debug-lines - add comments with debug line numbers if available
|
--add-debug-lines - add comments with debug line numbers if available
|
||||||
--no-inline-anonymous - disable anonymous classes inline
|
--no-inline-anonymous - disable anonymous classes inline
|
||||||
--no-inline-methods - disable methods inline
|
--no-inline-methods - disable methods inline
|
||||||
|
--no-move-inner-classes - disable move inner classes into parent
|
||||||
|
--no-inline-kotlin-lambda - disable inline for Kotlin lambdas
|
||||||
|
--no-finally - don't extract finally block
|
||||||
--no-replace-consts - don't replace constant value with matching constant field
|
--no-replace-consts - don't replace constant value with matching constant field
|
||||||
--escape-unicode - escape non latin characters in strings (with \u)
|
--escape-unicode - escape non latin characters in strings (with \u)
|
||||||
--respect-bytecode-access-modifiers - don't change original access modifiers
|
--respect-bytecode-access-modifiers - don't change original access modifiers
|
||||||
|
--mappings-path - deobfuscation mappings file or directory. Allowed formats: Tiny and Tiny v2 (both '.tiny'), Enigma (.mapping) or Enigma directory
|
||||||
|
--mappings-mode - set mode for handling the deobfuscation mapping file:
|
||||||
|
'read' - just read, user can always save manually (default)
|
||||||
|
'read-and-autosave-every-change' - read and autosave after every change
|
||||||
|
'read-and-autosave-before-closing' - read and autosave before exiting the app or closing the project
|
||||||
|
'ignore' - don't read or save (can be used to skip loading mapping files referenced in the project file)
|
||||||
--deobf - activate deobfuscation
|
--deobf - activate deobfuscation
|
||||||
--deobf-min - min length of name, renamed if shorter, default: 3
|
--deobf-min - min length of name, renamed if shorter, default: 3
|
||||||
--deobf-max - max length of name, renamed if longer, default: 64
|
--deobf-max - max length of name, renamed if longer, default: 64
|
||||||
--deobf-cfg-file - deobfuscation map file, default: same dir and name as input file with '.jobf' extension
|
--deobf-whitelist - space separated list of classes (full name) and packages (ends with '.*') to exclude from deobfuscation, default: android.support.v4.* android.support.v7.* android.support.v4.os.* android.support.annotation.Px androidx.core.os.* androidx.annotation.Px
|
||||||
--deobf-cfg-file-mode - set mode for handle deobfuscation map file:
|
--deobf-cfg-file - deobfuscation mappings file used for JADX auto-generated names (in the JOBF file format), default: same dir and name as input file with '.jobf' extension
|
||||||
|
--deobf-cfg-file-mode - set mode for handling the JADX auto-generated names' deobfuscation map file:
|
||||||
'read' - read if found, don't save (default)
|
'read' - read if found, don't save (default)
|
||||||
'read-or-save' - read if found, save otherwise (don't overwrite)
|
'read-or-save' - read if found, save otherwise (don't overwrite)
|
||||||
'overwrite' - don't read, always save
|
'overwrite' - don't read, always save
|
||||||
'ignore' - don't read and don't save
|
'ignore' - don't read and don't save
|
||||||
--deobf-use-sourcename - use source file name as class name alias
|
--deobf-use-sourcename - use source file name as class name alias
|
||||||
--deobf-parse-kotlin-metadata - parse kotlin metadata to class and package names
|
--deobf-res-name-source - better name source for resources:
|
||||||
|
'auto' - automatically select best name (default)
|
||||||
|
'resources' - use resources names
|
||||||
|
'code' - use R class fields names
|
||||||
--use-kotlin-methods-for-var-names - use kotlin intrinsic methods to rename variables, values: disable, apply, apply-and-hide, default: apply
|
--use-kotlin-methods-for-var-names - use kotlin intrinsic methods to rename variables, values: disable, apply, apply-and-hide, default: apply
|
||||||
--rename-flags - fix options (comma-separated list of):
|
--rename-flags - fix options (comma-separated list of):
|
||||||
'case' - fix case sensitivity issues (according to --fs-case-sensitive option),
|
'case' - fix case sensitivity issues (according to --fs-case-sensitive option),
|
||||||
@@ -123,6 +140,10 @@ options:
|
|||||||
'printable' - remove non-printable chars from identifiers,
|
'printable' - remove non-printable chars from identifiers,
|
||||||
or single 'none' - to disable all renames
|
or single 'none' - to disable all renames
|
||||||
or single 'all' - to enable all (default)
|
or single 'all' - to enable all (default)
|
||||||
|
--integer-format - how integers are displayed:
|
||||||
|
'auto' - automatically select (default)
|
||||||
|
'decimal' - use decimal
|
||||||
|
'hexadecimal' - use hexadecimal
|
||||||
--fs-case-sensitive - treat filesystem as case sensitive, false by default
|
--fs-case-sensitive - treat filesystem as case sensitive, false by default
|
||||||
--cfg - save methods control flow graph to dot file
|
--cfg - save methods control flow graph to dot file
|
||||||
--raw-cfg - save methods control flow graph (use raw instructions)
|
--raw-cfg - save methods control flow graph (use raw instructions)
|
||||||
@@ -141,6 +162,22 @@ Plugin options (-P<name>=<value>):
|
|||||||
2) java-convert: Convert .class, .jar and .aar files to dex
|
2) java-convert: Convert .class, .jar and .aar files to dex
|
||||||
- java-convert.mode - convert mode, values: [dx, d8, both], default: both
|
- java-convert.mode - convert mode, values: [dx, d8, both], default: both
|
||||||
- java-convert.d8-desugar - use desugar in d8, values: [yes, no], default: no
|
- java-convert.d8-desugar - use desugar in d8, values: [yes, no], default: no
|
||||||
|
3) kotlin-metadata: Use kotlin.Metadata annotation for code generation
|
||||||
|
- kotlin-metadata.class-alias - rename class alias, values: [yes, no], default: yes
|
||||||
|
- kotlin-metadata.method-args - rename function arguments, values: [yes, no], default: yes
|
||||||
|
- kotlin-metadata.fields - rename fields, values: [yes, no], default: yes
|
||||||
|
- kotlin-metadata.companion - rename companion object, values: [yes, no], default: yes
|
||||||
|
- kotlin-metadata.data-class - add data class modifier, values: [yes, no], default: yes
|
||||||
|
- kotlin-metadata.to-string - rename fields using toString, values: [yes, no], default: yes
|
||||||
|
- kotlin-metadata.getters - rename simple getters to field names, values: [yes, no], default: yes
|
||||||
|
4) rename-mappings: various mappings support
|
||||||
|
- rename-mappings.format - mapping format, values: [auto, TINY, TINY_2, ENIGMA, ENIGMA_DIR, MCP, SRG, TSRG, TSRG2, PROGUARD], default: auto
|
||||||
|
- rename-mappings.invert - invert mapping, values: [yes, no], default: no
|
||||||
|
|
||||||
|
Environment variables:
|
||||||
|
JADX_DISABLE_ZIP_SECURITY - set to 'true' to disable all security checks for zip files
|
||||||
|
JADX_ZIP_MAX_ENTRIES_COUNT - maximum allowed number of entries in zip files (default: 100 000)
|
||||||
|
JADX_TMP_DIR - custom temp directory, using system by default
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
jadx -d out classes.dex
|
jadx -d out classes.dex
|
||||||
|
|||||||
-160
@@ -1,160 +0,0 @@
|
|||||||
plugins {
|
|
||||||
id 'com.github.ben-manes.versions' version '0.42.0'
|
|
||||||
id 'com.diffplug.spotless' version '6.6.1'
|
|
||||||
}
|
|
||||||
|
|
||||||
ext.jadxVersion = System.getenv('JADX_VERSION') ?: "dev"
|
|
||||||
version = jadxVersion
|
|
||||||
println("jadx version: ${jadxVersion}")
|
|
||||||
|
|
||||||
allprojects {
|
|
||||||
apply plugin: 'java'
|
|
||||||
apply plugin: 'checkstyle'
|
|
||||||
|
|
||||||
version = jadxVersion
|
|
||||||
|
|
||||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
|
||||||
|
|
||||||
compileJava {
|
|
||||||
options.encoding = "UTF-8"
|
|
||||||
}
|
|
||||||
|
|
||||||
jar {
|
|
||||||
manifest {
|
|
||||||
mainAttributes('jadx-version': jadxVersion)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
implementation 'org.slf4j:slf4j-api:1.7.36'
|
|
||||||
compileOnly 'org.jetbrains:annotations:23.0.0'
|
|
||||||
|
|
||||||
testImplementation 'ch.qos.logback:logback-classic:1.2.11'
|
|
||||||
testImplementation 'org.hamcrest:hamcrest-library:2.2'
|
|
||||||
testImplementation 'org.mockito:mockito-core:4.6.0'
|
|
||||||
testImplementation 'org.assertj:assertj-core:3.22.0'
|
|
||||||
|
|
||||||
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.2'
|
|
||||||
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.2'
|
|
||||||
|
|
||||||
testCompileOnly 'org.jetbrains:annotations:23.0.0'
|
|
||||||
}
|
|
||||||
|
|
||||||
test {
|
|
||||||
useJUnitPlatform()
|
|
||||||
maxParallelForks = Runtime.runtime.availableProcessors()
|
|
||||||
}
|
|
||||||
|
|
||||||
repositories {
|
|
||||||
mavenLocal()
|
|
||||||
mavenCentral()
|
|
||||||
google()
|
|
||||||
// Commented out for now since we're using a local mapping-io fork atm.
|
|
||||||
// maven {
|
|
||||||
// name 'FabricMC'
|
|
||||||
// url 'https://maven.fabricmc.net/'
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
spotless {
|
|
||||||
java {
|
|
||||||
target fileTree(rootDir).matching {
|
|
||||||
include 'jadx-cli/src/**/java/**/*.java'
|
|
||||||
include 'jadx-core/src/**/java/**/*.java'
|
|
||||||
include 'jadx-gui/src/**/java/**/*.java'
|
|
||||||
include 'jadx-plugins/**/java/**/*.java'
|
|
||||||
}
|
|
||||||
|
|
||||||
importOrderFile 'config/code-formatter/eclipse.importorder'
|
|
||||||
eclipse().configFile 'config/code-formatter/eclipse.xml'
|
|
||||||
removeUnusedImports()
|
|
||||||
|
|
||||||
lineEndings(com.diffplug.spotless.LineEnding.UNIX)
|
|
||||||
encoding("UTF-8")
|
|
||||||
trimTrailingWhitespace()
|
|
||||||
endWithNewline()
|
|
||||||
}
|
|
||||||
format 'misc', {
|
|
||||||
target '**/*.gradle', '**/*.md', '**/*.xml', '**/.gitignore', '**/.properties'
|
|
||||||
targetExclude ".gradle/**", ".idea/**", "*/build/**"
|
|
||||||
|
|
||||||
lineEndings(com.diffplug.spotless.LineEnding.UNIX)
|
|
||||||
encoding("UTF-8")
|
|
||||||
trimTrailingWhitespace()
|
|
||||||
endWithNewline()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencyUpdates {
|
|
||||||
resolutionStrategy {
|
|
||||||
componentSelection { rules ->
|
|
||||||
rules.all { ComponentSelection selection ->
|
|
||||||
boolean rejected = ['alpha', 'beta', 'rc', 'cr', 'm', 'atlassian'].any { qualifier ->
|
|
||||||
selection.candidate.version ==~ /(?i).*[.-]${qualifier}[.\d-]*/
|
|
||||||
}
|
|
||||||
if (rejected) {
|
|
||||||
selection.reject('Release candidate')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
task copyArtifacts(type: Copy) {
|
|
||||||
from tasks.getByPath(":jadx-cli:installDist")
|
|
||||||
from tasks.getByPath(":jadx-gui:installDist")
|
|
||||||
into layout.buildDirectory.dir("jadx")
|
|
||||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
|
||||||
}
|
|
||||||
|
|
||||||
task pack(type: Zip) {
|
|
||||||
from copyArtifacts
|
|
||||||
archiveFileName = "jadx-${jadxVersion}.zip"
|
|
||||||
destinationDirectory = layout.buildDirectory
|
|
||||||
}
|
|
||||||
|
|
||||||
task copyExe(type: Copy) {
|
|
||||||
group 'jadx'
|
|
||||||
description = 'Copy exe to build dir'
|
|
||||||
mustRunAfter pack // not needed, but gradle throws warning because of same output dir
|
|
||||||
|
|
||||||
from tasks.getByPath('jadx-gui:createExe')
|
|
||||||
include '*.exe'
|
|
||||||
into layout.buildDirectory
|
|
||||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
|
||||||
}
|
|
||||||
|
|
||||||
task distWinBundle(type: Copy, dependsOn: 'jadx-gui:distWinWithJre') {
|
|
||||||
group 'jadx'
|
|
||||||
description = 'Copy bundle to build dir'
|
|
||||||
destinationDir buildDir
|
|
||||||
from(tasks.getByPath('jadx-gui:distWinWithJre').outputs) {
|
|
||||||
include '*.zip'
|
|
||||||
}
|
|
||||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
|
||||||
}
|
|
||||||
|
|
||||||
task dist {
|
|
||||||
group 'jadx'
|
|
||||||
description = 'Build jadx distribution zip'
|
|
||||||
|
|
||||||
dependsOn(pack)
|
|
||||||
|
|
||||||
OperatingSystem os = org.gradle.nativeplatform.platform.internal.DefaultNativePlatform.currentOperatingSystem;
|
|
||||||
if (os.isWindows()) {
|
|
||||||
if (project.hasProperty("bundleJRE")) {
|
|
||||||
println("Build win bundle with JRE")
|
|
||||||
dependsOn('distWinBundle')
|
|
||||||
} else {
|
|
||||||
dependsOn('copyExe')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
task cleanBuildDir(type: Delete) {
|
|
||||||
group 'jadx'
|
|
||||||
delete buildDir
|
|
||||||
}
|
|
||||||
|
|
||||||
clean.dependsOn(cleanBuildDir)
|
|
||||||
@@ -0,0 +1,154 @@
|
|||||||
|
import com.diffplug.gradle.spotless.FormatExtension
|
||||||
|
import com.diffplug.gradle.spotless.SpotlessExtension
|
||||||
|
import com.diffplug.spotless.LineEnding
|
||||||
|
import com.github.benmanes.gradle.versions.updates.DependencyUpdatesTask
|
||||||
|
import org.gradle.nativeplatform.platform.internal.DefaultNativePlatform
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
id("com.github.ben-manes.versions") version "0.51.0"
|
||||||
|
id("se.patrikerdes.use-latest-versions") version "0.2.18"
|
||||||
|
id("com.diffplug.spotless") version "6.25.0"
|
||||||
|
}
|
||||||
|
|
||||||
|
val jadxVersion by extra { System.getenv("JADX_VERSION") ?: "dev" }
|
||||||
|
println("jadx version: $jadxVersion")
|
||||||
|
version = jadxVersion
|
||||||
|
|
||||||
|
allprojects {
|
||||||
|
apply(plugin = "java")
|
||||||
|
apply(plugin = "checkstyle")
|
||||||
|
apply(plugin = "com.diffplug.spotless")
|
||||||
|
apply(plugin = "com.github.ben-manes.versions")
|
||||||
|
apply(plugin = "se.patrikerdes.use-latest-versions")
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
configure<SpotlessExtension> {
|
||||||
|
java {
|
||||||
|
importOrderFile("$rootDir/config/code-formatter/eclipse.importorder")
|
||||||
|
eclipse().configFile("$rootDir/config/code-formatter/eclipse.xml")
|
||||||
|
removeUnusedImports()
|
||||||
|
commonFormatOptions()
|
||||||
|
}
|
||||||
|
kotlin {
|
||||||
|
ktlint().editorConfigOverride(mapOf("indent_style" to "tab"))
|
||||||
|
commonFormatOptions()
|
||||||
|
}
|
||||||
|
kotlinGradle {
|
||||||
|
ktlint()
|
||||||
|
commonFormatOptions()
|
||||||
|
}
|
||||||
|
format("misc") {
|
||||||
|
target("**/*.gradle", "**/*.xml", "**/.gitignore", "**/.properties")
|
||||||
|
targetExclude(".gradle/**", ".idea/**", "*/build/**")
|
||||||
|
commonFormatOptions()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.named<DependencyUpdatesTask>("dependencyUpdates") {
|
||||||
|
rejectVersionIf {
|
||||||
|
// disallow release candidates as upgradable versions from stable versions
|
||||||
|
isNonStable(candidate.version) && !isNonStable(currentVersion)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun FormatExtension.commonFormatOptions() {
|
||||||
|
lineEndings = LineEnding.UNIX
|
||||||
|
encoding = Charsets.UTF_8
|
||||||
|
trimTrailingWhitespace()
|
||||||
|
endWithNewline()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isNonStable(version: String): Boolean {
|
||||||
|
val stableKeyword = listOf("RELEASE", "FINAL", "GA").any { version.uppercase(Locale.getDefault()).contains(it) }
|
||||||
|
val regex = "^[0-9,.v-]+(-r)?$".toRegex()
|
||||||
|
val isStable = stableKeyword || regex.matches(version)
|
||||||
|
return isStable.not()
|
||||||
|
}
|
||||||
|
|
||||||
|
val copyArtifacts by tasks.registering(Copy::class) {
|
||||||
|
val jarCliPattern = "jadx-cli-(.*)-all.jar".toPattern()
|
||||||
|
from(tasks.getByPath(":jadx-cli:installShadowDist")) {
|
||||||
|
exclude("**/*.jar")
|
||||||
|
filter { line ->
|
||||||
|
jarCliPattern.matcher(line).replaceAll("jadx-$1-all.jar")
|
||||||
|
.replace("-jar \"\\\"\$CLASSPATH\\\"\"", "-cp \"\\\"\$CLASSPATH\\\"\" jadx.cli.JadxCLI")
|
||||||
|
.replace("-jar \"%CLASSPATH%\"", "-cp \"%CLASSPATH%\" jadx.cli.JadxCLI")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val jarGuiPattern = "jadx-gui-(.*)-all.jar".toPattern()
|
||||||
|
from(tasks.getByPath(":jadx-gui:installShadowDist")) {
|
||||||
|
exclude("**/*.jar")
|
||||||
|
filter { line -> jarGuiPattern.matcher(line).replaceAll("jadx-$1-all.jar") }
|
||||||
|
}
|
||||||
|
from(tasks.getByPath(":jadx-gui:installShadowDist")) {
|
||||||
|
include("**/*.jar")
|
||||||
|
rename("jadx-gui-(.*)-all.jar", "jadx-$1-all.jar")
|
||||||
|
}
|
||||||
|
into(layout.buildDirectory.dir("jadx"))
|
||||||
|
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
||||||
|
}
|
||||||
|
|
||||||
|
val pack by tasks.registering(Zip::class) {
|
||||||
|
from(copyArtifacts)
|
||||||
|
archiveFileName.set("jadx-$jadxVersion.zip")
|
||||||
|
destinationDirectory.set(layout.buildDirectory)
|
||||||
|
}
|
||||||
|
|
||||||
|
val copyExe by tasks.registering(Copy::class) {
|
||||||
|
group = "jadx"
|
||||||
|
description = "Copy exe to build dir"
|
||||||
|
|
||||||
|
// next task dependencies not needed, but gradle throws warning because of same output dir
|
||||||
|
mustRunAfter("jar")
|
||||||
|
mustRunAfter(pack)
|
||||||
|
|
||||||
|
from(tasks.getByPath("jadx-gui:createExe"))
|
||||||
|
include("*.exe")
|
||||||
|
into(layout.buildDirectory)
|
||||||
|
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
||||||
|
}
|
||||||
|
|
||||||
|
val distWinBundle by tasks.registering(Copy::class) {
|
||||||
|
group = "jadx"
|
||||||
|
description = "Copy bundle to build dir"
|
||||||
|
|
||||||
|
dependsOn(tasks.getByPath(":jadx-gui:distWinWithJre"))
|
||||||
|
|
||||||
|
// next task dependencies not needed, but gradle throws warning because of same output dir
|
||||||
|
mustRunAfter("jar")
|
||||||
|
mustRunAfter(pack)
|
||||||
|
|
||||||
|
from(tasks.getByPath("jadx-gui:distWinWithJre").outputs) {
|
||||||
|
include("*.zip")
|
||||||
|
}
|
||||||
|
into(layout.buildDirectory)
|
||||||
|
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
||||||
|
}
|
||||||
|
|
||||||
|
val dist by tasks.registering {
|
||||||
|
group = "jadx"
|
||||||
|
description = "Build jadx distribution zip"
|
||||||
|
|
||||||
|
dependsOn(pack)
|
||||||
|
|
||||||
|
val os = DefaultNativePlatform.getCurrentOperatingSystem()
|
||||||
|
if (os.isWindows) {
|
||||||
|
if (project.hasProperty("bundleJRE")) {
|
||||||
|
println("Build win bundle with JRE")
|
||||||
|
dependsOn(distWinBundle)
|
||||||
|
} else {
|
||||||
|
dependsOn(copyExe)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val cleanBuildDir by tasks.registering(Delete::class) {
|
||||||
|
group = "jadx"
|
||||||
|
delete(layout.buildDirectory)
|
||||||
|
}
|
||||||
|
tasks.getByName("clean").dependsOn(cleanBuildDir)
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
plugins {
|
|
||||||
id 'groovy-gradle-plugin'
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
plugins {
|
||||||
|
`kotlin-dsl`
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.22")
|
||||||
|
}
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
gradlePluginPortal()
|
||||||
|
}
|
||||||
@@ -1,79 +0,0 @@
|
|||||||
plugins {
|
|
||||||
id 'java-library'
|
|
||||||
id 'maven-publish'
|
|
||||||
id 'signing'
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
group = 'io.github.skylot'
|
|
||||||
version = jadxVersion
|
|
||||||
|
|
||||||
java {
|
|
||||||
withJavadocJar()
|
|
||||||
withSourcesJar()
|
|
||||||
}
|
|
||||||
|
|
||||||
publishing {
|
|
||||||
publications {
|
|
||||||
mavenJava(MavenPublication) {
|
|
||||||
artifactId = project.name
|
|
||||||
from components.java
|
|
||||||
versionMapping {
|
|
||||||
usage('java-api') {
|
|
||||||
fromResolutionOf('runtimeClasspath')
|
|
||||||
}
|
|
||||||
usage('java-runtime') {
|
|
||||||
fromResolutionResult()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pom {
|
|
||||||
name = project.name
|
|
||||||
description = 'Dex to Java decompiler'
|
|
||||||
url = 'https://github.com/skylot/jadx'
|
|
||||||
licenses {
|
|
||||||
license {
|
|
||||||
name = 'The Apache License, Version 2.0'
|
|
||||||
url = 'http://www.apache.org/licenses/LICENSE-2.0.txt'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
developers {
|
|
||||||
developer {
|
|
||||||
id = 'skylot'
|
|
||||||
name = 'Skylot'
|
|
||||||
email = 'skylot@gmail.com'
|
|
||||||
url = 'https://github.com/skylot'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
scm {
|
|
||||||
connection = 'scm:git:git://github.com/skylot/jadx.git'
|
|
||||||
developerConnection = 'scm:git:ssh://github.com:skylot/jadx.git'
|
|
||||||
url = 'https://github.com/skylot/jadx'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
repositories {
|
|
||||||
maven {
|
|
||||||
def releasesRepoUrl = uri('https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/')
|
|
||||||
def snapshotsRepoUrl = uri('https://s01.oss.sonatype.org/content/repositories/snapshots/')
|
|
||||||
url = version.endsWith('SNAPSHOT') ? snapshotsRepoUrl : releasesRepoUrl
|
|
||||||
credentials {
|
|
||||||
username = project.properties['ossrhUser'].toString()
|
|
||||||
password = project.properties['ossrhPassword'].toString()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
signing {
|
|
||||||
required { gradle.taskGraph.hasTask("publish") }
|
|
||||||
sign publishing.publications.mavenJava
|
|
||||||
}
|
|
||||||
|
|
||||||
javadoc {
|
|
||||||
if (JavaVersion.current().isJava9Compatible()) {
|
|
||||||
options.addBooleanOption('html5', true)
|
|
||||||
}
|
|
||||||
// disable 'missing' warnings
|
|
||||||
options.addStringOption('Xdoclint:all,-missing', '-quiet')
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
import org.gradle.api.tasks.testing.logging.TestExceptionFormat
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
java
|
||||||
|
checkstyle
|
||||||
|
}
|
||||||
|
|
||||||
|
val jadxVersion: String by rootProject.extra
|
||||||
|
|
||||||
|
group = "io.github.skylot"
|
||||||
|
version = jadxVersion
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation("org.slf4j:slf4j-api:2.0.11")
|
||||||
|
compileOnly("org.jetbrains:annotations:24.1.0")
|
||||||
|
|
||||||
|
testImplementation("ch.qos.logback:logback-classic:1.4.14")
|
||||||
|
testImplementation("org.hamcrest:hamcrest-library:2.2")
|
||||||
|
testImplementation("org.mockito:mockito-core:5.10.0")
|
||||||
|
testImplementation("org.assertj:assertj-core:3.25.2")
|
||||||
|
|
||||||
|
testImplementation("org.junit.jupiter:junit-jupiter:5.10.1")
|
||||||
|
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
|
||||||
|
|
||||||
|
testCompileOnly("org.jetbrains:annotations:24.1.0")
|
||||||
|
}
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
// required for: aapt-proto, r8, smali
|
||||||
|
google()
|
||||||
|
}
|
||||||
|
|
||||||
|
java {
|
||||||
|
sourceCompatibility = JavaVersion.VERSION_11
|
||||||
|
targetCompatibility = JavaVersion.VERSION_11
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks {
|
||||||
|
compileJava {
|
||||||
|
options.encoding = "UTF-8"
|
||||||
|
}
|
||||||
|
jar {
|
||||||
|
manifest {
|
||||||
|
attributes("jadx-version" to jadxVersion)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
test {
|
||||||
|
useJUnitPlatform()
|
||||||
|
maxParallelForks = Runtime.getRuntime().availableProcessors()
|
||||||
|
testLogging {
|
||||||
|
showExceptions = true
|
||||||
|
exceptionFormat = TestExceptionFormat.FULL
|
||||||
|
showCauses = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
id("jadx-java")
|
||||||
|
id("org.jetbrains.kotlin.jvm")
|
||||||
|
}
|
||||||
|
|
||||||
|
kotlin {
|
||||||
|
compilerOptions {
|
||||||
|
jvmTarget.set(JvmTarget.JVM_11)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
plugins {
|
||||||
|
id("jadx-java")
|
||||||
|
id("java-library")
|
||||||
|
id("maven-publish")
|
||||||
|
id("signing")
|
||||||
|
}
|
||||||
|
|
||||||
|
val jadxVersion: String by rootProject.extra
|
||||||
|
|
||||||
|
group = "io.github.skylot"
|
||||||
|
version = jadxVersion
|
||||||
|
|
||||||
|
java {
|
||||||
|
withJavadocJar()
|
||||||
|
withSourcesJar()
|
||||||
|
}
|
||||||
|
|
||||||
|
publishing {
|
||||||
|
publications {
|
||||||
|
create<MavenPublication>("mavenJava") {
|
||||||
|
artifactId = project.name
|
||||||
|
from(components["java"])
|
||||||
|
versionMapping {
|
||||||
|
usage("java-api") {
|
||||||
|
fromResolutionOf("runtimeClasspath")
|
||||||
|
}
|
||||||
|
usage("java-runtime") {
|
||||||
|
fromResolutionResult()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pom {
|
||||||
|
name.set(project.name)
|
||||||
|
description.set("Dex to Java decompiler")
|
||||||
|
url.set("https://github.com/skylot/jadx")
|
||||||
|
licenses {
|
||||||
|
license {
|
||||||
|
name.set("The Apache License, Version 2.0")
|
||||||
|
url.set("http://www.apache.org/licenses/LICENSE-2.0.txt")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
developers {
|
||||||
|
developer {
|
||||||
|
id.set("skylot")
|
||||||
|
name.set("Skylot")
|
||||||
|
email.set("skylot@gmail.com")
|
||||||
|
url.set("https://github.com/skylot")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
scm {
|
||||||
|
connection .set("scm:git:git://github.com/skylot/jadx.git")
|
||||||
|
developerConnection.set("scm:git:ssh://github.com:skylot/jadx.git")
|
||||||
|
url .set("https://github.com/skylot/jadx")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
repositories {
|
||||||
|
maven {
|
||||||
|
val releasesRepoUrl = uri("https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/")
|
||||||
|
val snapshotsRepoUrl = uri("https://s01.oss.sonatype.org/content/repositories/snapshots/")
|
||||||
|
url = if (version.toString().endsWith("SNAPSHOT")) snapshotsRepoUrl else releasesRepoUrl
|
||||||
|
credentials {
|
||||||
|
username = project.properties["ossrhUser"].toString()
|
||||||
|
password = project.properties["ossrhPassword"].toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
signing {
|
||||||
|
isRequired = gradle.taskGraph.hasTask("publish")
|
||||||
|
sign(publishing.publications["mavenJava"])
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
tasks.javadoc {
|
||||||
|
val stdOptions = options as StandardJavadocDocletOptions
|
||||||
|
stdOptions.addBooleanOption("html5", true)
|
||||||
|
// disable 'missing' warnings
|
||||||
|
stdOptions.addStringOption("Xdoclint:all,-missing", "-quiet")
|
||||||
|
}
|
||||||
+222
-170
@@ -1,77 +1,248 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
<profiles version="16">
|
<profiles version="23">
|
||||||
<profile kind="CodeFormatterProfile" name="jadx eclipse" version="16">
|
<profile kind="CodeFormatterProfile" name="jadx eclipse" version="23">
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_ellipsis" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_ellipsis" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_for_statment" value="common_lines"/>
|
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_for_statment" value="common_lines"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries" value="true"/>
|
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries" value="true"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_logical_operator" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_method_invocation" value="common_lines"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_imports" value="1"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_switch_statement" value="common_lines"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_javadoc_comments" value="true"/>
|
<setting id="org.eclipse.jdt.core.formatter.comment.format_javadoc_comments" value="true"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.indentation.size" value="4"/>
|
<setting id="org.eclipse.jdt.core.formatter.indentation.size" value="4"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_enum_constant_declaration" value="common_lines"/>
|
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_enum_constant_declaration" value="common_lines"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.align_with_spaces" value="false"/>
|
<setting id="org.eclipse.jdt.core.formatter.align_with_spaces" value="false"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.disabling_tag" value="@formatter:off"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation" value="2"/>
|
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation" value="2"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_enum_constants" value="48"/>
|
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_before_code_block" value="0"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_imports" value="1"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_switch_case_expressions" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_package" value="1"/>
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_package" value="1"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_if_while_statement" value="common_lines"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant" value="16"/>
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant" value="16"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.comment.indent_root_tags" value="false"/>
|
<setting id="org.eclipse.jdt.core.formatter.comment.indent_root_tags" value="false"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch" value="true"/>
|
<setting id="org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch" value="true"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.enabling_tag" value="@formatter:on"/>
|
<setting id="org.eclipse.jdt.core.formatter.enabling_tag" value="@formatter:on"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.comment.count_line_length_from_starting_position" value="true"/>
|
<setting id="org.eclipse.jdt.core.formatter.comment.count_line_length_from_starting_position" value="true"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_record_components" value="16"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="16"/>
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="16"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_multiplicative_operator" value="true"/>
|
<setting id="org.eclipse.jdt.core.formatter.wrap_before_multiplicative_operator" value="true"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line" value="false"/>
|
<setting id="org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line" value="false"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations" value="1"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameterized_type_references" value="0"/>
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameterized_type_references" value="0"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_logical_operator" value="16"/>
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_logical_operator" value="16"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.keep_annotation_declaration_on_one_line" value="one_line_never"/>
|
<setting id="org.eclipse.jdt.core.formatter.keep_annotation_declaration_on_one_line" value="one_line_never"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_record_declaration" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_enum_constant" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_enum_constant" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_multiplicative_operator" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_multiplicative_operator" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column" value="false"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_abstract_method" value="1"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.keep_enum_constant_declaration_on_one_line" value="one_line_never"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.align_variable_declarations_on_columns" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_catch_clause" value="common_lines"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiplicative_operator" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.keep_anonymous_type_declaration_on_one_line" value="one_line_never"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_switch_case_expressions" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.wrap_before_shift_operator" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block" value="end_of_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_end_of_code_block" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_bitwise_operator" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_type_parameters" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_loops" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.keep_simple_for_body_on_same_line" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.wrap_before_switch_case_arrow_operator" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_unary_operator" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_annotation" value="separate_lines_if_wrapped"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_ellipsis" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_enum_constant" value="49"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.text_block_indentation" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.align_type_members_on_columns" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_assignment" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_module_statements" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.align_tags_names_descriptions" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.keep_if_then_body_block_on_one_line" value="one_line_never"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_permitted_types" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case" value="end_of_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression_chain" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.format_header" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_type_annotations" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.wrap_before_assertion_message_operator" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_method_declaration" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines" value="2147483647"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_bitwise_operator" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration" value="end_of_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_resources_in_try" value="80"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.format_source_code" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_field" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_method" value="1"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_not_operator" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.format_html" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_method_delcaration" value="common_lines"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_if" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.indent_empty_lines" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_type_arguments" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_unary_operator" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_package" value="49"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_label" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_arrow_in_switch_case" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_permitted_types_in_type_declaration" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_record_header" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.wrap_before_bitwise_operator" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.indent_tag_description" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_record_constructor" value="end_of_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_string_concatenation" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiple_fields" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_array_initializer" value="end_of_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_shift_operator" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_shift_operator" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.keep_simple_do_while_body_on_same_line" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_record_components" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_for_loop_header" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.wrap_before_additive_operator" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.keep_simple_getter_setter_on_one_line" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_string_concatenation" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.join_lines_in_comments" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_record_declaration" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_relational_operator" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_import_groups" value="1"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_logical_operator" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_method_invocation" value="common_lines"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_imports" value="1"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_record_declaration" value="common_lines"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_switch_statement" value="common_lines"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_arrow_in_switch_default" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.disabling_tag" value="@formatter:off"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_enum_constants" value="48"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_imports" value="1"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_end_of_method_body" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_if_while_statement" value="common_lines"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_arrow_in_switch_case" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations" value="1"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.keep_switch_body_block_on_one_line" value="one_line_never"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column" value="false"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_block" value="true"/>
|
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_block" value="true"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration" value="end_of_line"/>
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration" value="end_of_line"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_switch_case_with_arrow" value="0"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.comment.align_tags_descriptions_grouped" value="true"/>
|
<setting id="org.eclipse.jdt.core.formatter.comment.align_tags_descriptions_grouped" value="true"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.comment.line_length" value="100"/>
|
<setting id="org.eclipse.jdt.core.formatter.comment.line_length" value="100"/>
|
||||||
@@ -80,267 +251,148 @@
|
|||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.keep_loop_body_block_on_one_line" value="one_line_never"/>
|
<setting id="org.eclipse.jdt.core.formatter.keep_loop_body_block_on_one_line" value="one_line_never"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments" value="false"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_method_declaration" value="end_of_line"/>
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_method_declaration" value="end_of_line"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.keep_enum_constant_declaration_on_one_line" value="one_line_never"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.align_variable_declarations_on_columns" value="false"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch" value="16"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.keep_type_declaration_on_one_line" value="one_line_never"/>
|
<setting id="org.eclipse.jdt.core.formatter.keep_type_declaration_on_one_line" value="one_line_never"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body" value="0"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line" value="false"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_catch_clause" value="common_lines"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_additive_operator" value="16"/>
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_additive_operator" value="16"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_record_constructor" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call" value="16"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_relational_operator" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_relational_operator" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiplicative_operator" value="16"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.keep_anonymous_type_declaration_on_one_line" value="one_line_never"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_shift_operator" value="true"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header" value="true"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.keep_record_declaration_on_one_line" value="one_line_never"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block" value="end_of_line"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration" value="end_of_line"/>
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration" value="end_of_line"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_lambda_body" value="end_of_line"/>
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_lambda_body" value="end_of_line"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.compact_else_if" value="true"/>
|
<setting id="org.eclipse.jdt.core.formatter.compact_else_if" value="true"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_bitwise_operator" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line" value="true"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration" value="16"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_type_parameters" value="0"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation" value="16"/>
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation" value="16"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration" value="16"/>
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration" value="16"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_loops" value="16"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment" value="true"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.keep_simple_for_body_on_same_line" value="false"/>
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_parameter" value="0"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment" value="false"/>
|
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment" value="false"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_relational_operator" value="0"/>
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_relational_operator" value="0"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_unary_operator" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer" value="16"/>
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer" value="16"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column" value="true"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve" value="1"/>
|
<setting id="org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve" value="1"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_annotation" value="separate_lines_if_wrapped"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_ellipsis" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_additive_operator" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_additive_operator" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_string_concatenation" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_string_concatenation" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_line_comments" value="true"/>
|
<setting id="org.eclipse.jdt.core.formatter.comment.format_line_comments" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.align_selector_in_method_invocation_on_expression_first_line" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_record_declaration" value="end_of_line"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.align_type_members_on_columns" value="false"/>
|
<setting id="org.eclipse.jdt.core.formatter.keep_switch_case_with_arrow_on_one_line" value="one_line_never"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_assignment" value="16"/>
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_switch_case_with_colon" value="0"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_module_statements" value="16"/>
|
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_after_code_block" value="0"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header" value="true"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.comment.align_tags_names_descriptions" value="false"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration" value="16"/>
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration" value="16"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.keep_if_then_body_block_on_one_line" value="one_line_never"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration" value="0"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression" value="48"/>
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression" value="48"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line" value="false"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns" value="false"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_type" value="49"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_local_variable" value="49"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration" value="end_of_line"/>
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration" value="end_of_line"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case" value="end_of_line"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_arrow_in_switch_default" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_between_different_tags" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression_chain" value="16"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_header" value="true"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression" value="16"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_additive_operator" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_additive_operator" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_method_declaration" value="0"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.join_wrapped_lines" value="false"/>
|
<setting id="org.eclipse.jdt.core.formatter.join_wrapped_lines" value="false"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_field" value="49"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_conditional_operator" value="true"/>
|
<setting id="org.eclipse.jdt.core.formatter.wrap_before_conditional_operator" value="true"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases" value="true"/>
|
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases" value="true"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_shift_operator" value="0"/>
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_shift_operator" value="0"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines" value="2147483647"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries" value="true"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_bitwise_operator" value="16"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration" value="end_of_line"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_resources_in_try" value="80"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations" value="false"/>
|
<setting id="org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations" value="false"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_try_clause" value="common_lines"/>
|
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_try_clause" value="common_lines"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation" value="16"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column" value="false"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.keep_code_block_on_one_line" value="one_line_never"/>
|
<setting id="org.eclipse.jdt.core.formatter.keep_code_block_on_one_line" value="one_line_never"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_record_components" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.tabulation.size" value="4"/>
|
<setting id="org.eclipse.jdt.core.formatter.tabulation.size" value="4"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_bitwise_operator" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_bitwise_operator" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_source_code" value="true"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_field" value="0"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer" value="2"/>
|
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer" value="2"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_method" value="1"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_record_declaration" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration" value="16"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration" value="16"/>
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration" value="16"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_assignment_operator" value="false"/>
|
<setting id="org.eclipse.jdt.core.formatter.wrap_before_assignment_operator" value="false"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_switch" value="end_of_line"/>
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_switch" value="end_of_line"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_html" value="true"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_method_delcaration" value="common_lines"/>
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_switch_case_with_arrow" value="0"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_if" value="16"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.keep_lambda_body_block_on_one_line" value="one_line_never"/>
|
<setting id="org.eclipse.jdt.core.formatter.keep_lambda_body_block_on_one_line" value="one_line_never"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.indent_empty_lines" value="false"/>
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_method" value="49"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_type_arguments" value="0"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_unary_operator" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.keep_record_constructor_on_one_line" value="one_line_never"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_record_declaration" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation" value="16"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line" value="false"/>
|
<setting id="org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line" value="false"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch" value="true"/>
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_assertion_message" value="0"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk" value="1"/>
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk" value="1"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_label" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header" value="true"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_member_type" value="1"/>
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_member_type" value="1"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_logical_operator" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_logical_operator" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression" value="16"/>
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression" value="16"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_record_declaration" value="16"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases" value="true"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_bitwise_operator" value="true"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_relational_operator" value="true"/>
|
<setting id="org.eclipse.jdt.core.formatter.wrap_before_relational_operator" value="true"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_block_comments" value="true"/>
|
<setting id="org.eclipse.jdt.core.formatter.comment.format_block_comments" value="true"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.comment.indent_tag_description" value="false"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line" value="false"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration" value="16"/>
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration" value="16"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_string_concatenation" value="16"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_last_class_body_declaration" value="0"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_body" value="true"/>
|
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_body" value="true"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiple_fields" value="16"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.keep_simple_while_body_on_same_line" value="false"/>
|
<setting id="org.eclipse.jdt.core.formatter.keep_simple_while_body_on_same_line" value="false"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_array_initializer" value="end_of_line"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_logical_operator" value="true"/>
|
<setting id="org.eclipse.jdt.core.formatter.wrap_before_logical_operator" value="true"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_shift_operator" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_statement_group_in_switch" value="0"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_lambda_declaration" value="common_lines"/>
|
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_lambda_declaration" value="common_lines"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_shift_operator" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_permitted_types" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.keep_simple_do_while_body_on_same_line" value="false"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.keep_enum_declaration_on_one_line" value="one_line_never"/>
|
<setting id="org.eclipse.jdt.core.formatter.keep_enum_declaration_on_one_line" value="one_line_never"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested" value="true"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_constant" value="end_of_line"/>
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_constant" value="end_of_line"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_type_declaration" value="end_of_line"/>
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_type_declaration" value="end_of_line"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_multiplicative_operator" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_multiplicative_operator" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_package" value="0"/>
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_package" value="0"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_for_loop_header" value="0"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_additive_operator" value="true"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.keep_simple_getter_setter_on_one_line" value="false"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header" value="true"/>
|
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header" value="true"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_string_concatenation" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.join_lines_in_comments" value="false"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.comment.indent_parameter_description" value="false"/>
|
<setting id="org.eclipse.jdt.core.formatter.comment.indent_parameter_description" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_code_block" value="0"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.tabulation.char" value="tab"/>
|
<setting id="org.eclipse.jdt.core.formatter.tabulation.char" value="tab"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_relational_operator" value="insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations" value="do not insert"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_string_concatenation" value="true"/>
|
<setting id="org.eclipse.jdt.core.formatter.wrap_before_string_concatenation" value="true"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_import_groups" value="1"/>
|
|
||||||
<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="140"/>
|
<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="140"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch" value="insert"/>
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
org.gradle.warning.mode=all
|
org.gradle.warning.mode=all
|
||||||
org.gradle.parallel=true
|
org.gradle.parallel=true
|
||||||
|
org.gradle.caching=true
|
||||||
|
|
||||||
# Flags for google-java-format (optimize imports by spotless) for Java >= 16.
|
# Flags for google-java-format (optimize imports by spotless) for Java >= 16.
|
||||||
# Java < 9 will ignore unsupported flags (thanks to -XX:+IgnoreUnrecognizedVMOptions)
|
# Java < 9 will ignore unsupported flags (thanks to -XX:+IgnoreUnrecognizedVMOptions)
|
||||||
|
|||||||
Vendored
BIN
Binary file not shown.
+4
-2
@@ -1,6 +1,8 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionSha256Sum=29e49b10984e585d8118b7d0bc452f944e386458df27371b49b4ac1dec4b7fda
|
distributionSha256Sum=9d926787066a081739e8200858338b4a69e837c3a821a33aca9db09dd4a41026
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
|
||||||
|
networkTimeout=10000
|
||||||
|
validateDistributionUrl=true
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
|||||||
@@ -55,7 +55,7 @@
|
|||||||
# Darwin, MinGW, and NonStop.
|
# Darwin, MinGW, and NonStop.
|
||||||
#
|
#
|
||||||
# (3) This script is generated from the Groovy template
|
# (3) This script is generated from the Groovy template
|
||||||
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||||
# within the Gradle project.
|
# within the Gradle project.
|
||||||
#
|
#
|
||||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||||
@@ -80,13 +80,11 @@ do
|
|||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
|
# This is normally unused
|
||||||
|
# shellcheck disable=SC2034
|
||||||
APP_NAME="Gradle"
|
|
||||||
APP_BASE_NAME=${0##*/}
|
APP_BASE_NAME=${0##*/}
|
||||||
|
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
|
||||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
|
||||||
|
|
||||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
MAX_FD=maximum
|
MAX_FD=maximum
|
||||||
@@ -133,22 +131,29 @@ location of your Java installation."
|
|||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
JAVACMD=java
|
JAVACMD=java
|
||||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
if ! command -v java >/dev/null 2>&1
|
||||||
|
then
|
||||||
|
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
|
||||||
Please set the JAVA_HOME variable in your environment to match the
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
location of your Java installation."
|
location of your Java installation."
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Increase the maximum file descriptors if we can.
|
# Increase the maximum file descriptors if we can.
|
||||||
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||||
case $MAX_FD in #(
|
case $MAX_FD in #(
|
||||||
max*)
|
max*)
|
||||||
|
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
||||||
|
# shellcheck disable=SC2039,SC3045
|
||||||
MAX_FD=$( ulimit -H -n ) ||
|
MAX_FD=$( ulimit -H -n ) ||
|
||||||
warn "Could not query maximum file descriptor limit"
|
warn "Could not query maximum file descriptor limit"
|
||||||
esac
|
esac
|
||||||
case $MAX_FD in #(
|
case $MAX_FD in #(
|
||||||
'' | soft) :;; #(
|
'' | soft) :;; #(
|
||||||
*)
|
*)
|
||||||
|
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
||||||
|
# shellcheck disable=SC2039,SC3045
|
||||||
ulimit -n "$MAX_FD" ||
|
ulimit -n "$MAX_FD" ||
|
||||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||||
esac
|
esac
|
||||||
@@ -193,11 +198,15 @@ if "$cygwin" || "$msys" ; then
|
|||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Collect all arguments for the java command;
|
|
||||||
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
|
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
# shell script including quotes and variable substitutions, so put them in
|
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||||
# double quotes to make sure that they get re-expanded; and
|
|
||||||
# * put everything else in single quotes, so that it's not re-expanded.
|
# Collect all arguments for the java command:
|
||||||
|
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||||
|
# and any embedded shellness will be escaped.
|
||||||
|
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
||||||
|
# treated as '${Hostname}' itself on the command line.
|
||||||
|
|
||||||
set -- \
|
set -- \
|
||||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||||
@@ -205,6 +214,12 @@ set -- \
|
|||||||
org.gradle.wrapper.GradleWrapperMain \
|
org.gradle.wrapper.GradleWrapperMain \
|
||||||
"$@"
|
"$@"
|
||||||
|
|
||||||
|
# Stop when "xargs" is not available.
|
||||||
|
if ! command -v xargs >/dev/null 2>&1
|
||||||
|
then
|
||||||
|
die "xargs is not available"
|
||||||
|
fi
|
||||||
|
|
||||||
# Use "xargs" to parse quoted args.
|
# Use "xargs" to parse quoted args.
|
||||||
#
|
#
|
||||||
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||||
|
|||||||
Vendored
+9
-6
@@ -14,7 +14,7 @@
|
|||||||
@rem limitations under the License.
|
@rem limitations under the License.
|
||||||
@rem
|
@rem
|
||||||
|
|
||||||
@if "%DEBUG%" == "" @echo off
|
@if "%DEBUG%"=="" @echo off
|
||||||
@rem ##########################################################################
|
@rem ##########################################################################
|
||||||
@rem
|
@rem
|
||||||
@rem Gradle startup script for Windows
|
@rem Gradle startup script for Windows
|
||||||
@@ -25,7 +25,8 @@
|
|||||||
if "%OS%"=="Windows_NT" setlocal
|
if "%OS%"=="Windows_NT" setlocal
|
||||||
|
|
||||||
set DIRNAME=%~dp0
|
set DIRNAME=%~dp0
|
||||||
if "%DIRNAME%" == "" set DIRNAME=.
|
if "%DIRNAME%"=="" set DIRNAME=.
|
||||||
|
@rem This is normally unused
|
||||||
set APP_BASE_NAME=%~n0
|
set APP_BASE_NAME=%~n0
|
||||||
set APP_HOME=%DIRNAME%
|
set APP_HOME=%DIRNAME%
|
||||||
|
|
||||||
@@ -40,7 +41,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome
|
|||||||
|
|
||||||
set JAVA_EXE=java.exe
|
set JAVA_EXE=java.exe
|
||||||
%JAVA_EXE% -version >NUL 2>&1
|
%JAVA_EXE% -version >NUL 2>&1
|
||||||
if "%ERRORLEVEL%" == "0" goto execute
|
if %ERRORLEVEL% equ 0 goto execute
|
||||||
|
|
||||||
echo.
|
echo.
|
||||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
@@ -75,13 +76,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
|||||||
|
|
||||||
:end
|
:end
|
||||||
@rem End local scope for the variables with windows NT shell
|
@rem End local scope for the variables with windows NT shell
|
||||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
if %ERRORLEVEL% equ 0 goto mainEnd
|
||||||
|
|
||||||
:fail
|
:fail
|
||||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||||
rem the _cmd.exe /c_ return code!
|
rem the _cmd.exe /c_ return code!
|
||||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
set EXIT_CODE=%ERRORLEVEL%
|
||||||
exit /b 1
|
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||||
|
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||||
|
exit /b %EXIT_CODE%
|
||||||
|
|
||||||
:mainEnd
|
:mainEnd
|
||||||
if "%OS%"=="Windows_NT" endlocal
|
if "%OS%"=="Windows_NT" endlocal
|
||||||
|
|||||||
@@ -1,30 +0,0 @@
|
|||||||
plugins {
|
|
||||||
id 'application'
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
implementation(project(':jadx-core'))
|
|
||||||
|
|
||||||
runtimeOnly(project(':jadx-plugins:jadx-dex-input'))
|
|
||||||
runtimeOnly(project(':jadx-plugins:jadx-java-input'))
|
|
||||||
runtimeOnly(project(':jadx-plugins:jadx-java-convert'))
|
|
||||||
runtimeOnly(project(':jadx-plugins:jadx-smali-input'))
|
|
||||||
|
|
||||||
implementation 'com.beust:jcommander:1.82'
|
|
||||||
implementation 'ch.qos.logback:logback-classic:1.2.11'
|
|
||||||
}
|
|
||||||
|
|
||||||
application {
|
|
||||||
applicationName = 'jadx'
|
|
||||||
mainClass.set('jadx.cli.JadxCLI')
|
|
||||||
applicationDefaultJvmArgs = ['-Xms128M', '-XX:MaxRAMPercentage=70.0', '-XX:+UseG1GC']
|
|
||||||
}
|
|
||||||
|
|
||||||
applicationDistribution.with {
|
|
||||||
into('') {
|
|
||||||
from '../.'
|
|
||||||
include 'README.md'
|
|
||||||
include 'NOTICE'
|
|
||||||
include 'LICENSE'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
plugins {
|
||||||
|
id("jadx-java")
|
||||||
|
id("application")
|
||||||
|
|
||||||
|
// use shadow only for application scripts, jar will be copied from jadx-gui
|
||||||
|
id("com.github.johnrengelman.shadow") version "8.1.1"
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation(project(":jadx-core"))
|
||||||
|
implementation(project(":jadx-plugins-tools"))
|
||||||
|
|
||||||
|
runtimeOnly(project(":jadx-plugins:jadx-dex-input"))
|
||||||
|
runtimeOnly(project(":jadx-plugins:jadx-java-input"))
|
||||||
|
runtimeOnly(project(":jadx-plugins:jadx-java-convert"))
|
||||||
|
runtimeOnly(project(":jadx-plugins:jadx-smali-input"))
|
||||||
|
runtimeOnly(project(":jadx-plugins:jadx-rename-mappings"))
|
||||||
|
runtimeOnly(project(":jadx-plugins:jadx-kotlin-metadata"))
|
||||||
|
runtimeOnly(project(":jadx-plugins:jadx-script:jadx-script-plugin"))
|
||||||
|
runtimeOnly(project(":jadx-plugins:jadx-xapk-input"))
|
||||||
|
|
||||||
|
implementation("org.jcommander:jcommander:1.83")
|
||||||
|
implementation("ch.qos.logback:logback-classic:1.4.14")
|
||||||
|
}
|
||||||
|
|
||||||
|
application {
|
||||||
|
applicationName = "jadx"
|
||||||
|
mainClass.set("jadx.cli.JadxCLI")
|
||||||
|
applicationDefaultJvmArgs =
|
||||||
|
listOf(
|
||||||
|
"-Xms256M",
|
||||||
|
"-XX:MaxRAMPercentage=70.0",
|
||||||
|
// disable zip checks (#1962)
|
||||||
|
"-Djdk.util.zip.disableZip64ExtraFieldValidation=true",
|
||||||
|
)
|
||||||
|
applicationDistribution.from("$rootDir") {
|
||||||
|
include("README.md")
|
||||||
|
include("NOTICE")
|
||||||
|
include("LICENSE")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.shadowJar {
|
||||||
|
// shadow jar not needed
|
||||||
|
configurations = listOf()
|
||||||
|
}
|
||||||
@@ -17,19 +17,26 @@ import com.beust.jcommander.ParameterDescription;
|
|||||||
import com.beust.jcommander.ParameterException;
|
import com.beust.jcommander.ParameterException;
|
||||||
import com.beust.jcommander.Parameterized;
|
import com.beust.jcommander.Parameterized;
|
||||||
|
|
||||||
|
import jadx.api.JadxArgs;
|
||||||
import jadx.api.JadxDecompiler;
|
import jadx.api.JadxDecompiler;
|
||||||
import jadx.api.plugins.JadxPlugin;
|
|
||||||
import jadx.api.plugins.JadxPluginInfo;
|
import jadx.api.plugins.JadxPluginInfo;
|
||||||
import jadx.api.plugins.JadxPluginManager;
|
|
||||||
import jadx.api.plugins.options.JadxPluginOptions;
|
import jadx.api.plugins.options.JadxPluginOptions;
|
||||||
import jadx.api.plugins.options.OptionDescription;
|
import jadx.api.plugins.options.OptionDescription;
|
||||||
|
import jadx.core.plugins.JadxPluginManager;
|
||||||
|
import jadx.core.plugins.PluginContext;
|
||||||
import jadx.core.utils.Utils;
|
import jadx.core.utils.Utils;
|
||||||
|
import jadx.plugins.tools.JadxExternalPluginsLoader;
|
||||||
|
|
||||||
public class JCommanderWrapper<T> {
|
public class JCommanderWrapper<T> {
|
||||||
private final JCommander jc;
|
private final JCommander jc;
|
||||||
|
private final JadxCLIArgs argsObj;
|
||||||
|
|
||||||
public JCommanderWrapper(T obj) {
|
public JCommanderWrapper(JadxCLIArgs argsObj) {
|
||||||
this.jc = JCommander.newBuilder().addObject(obj).build();
|
JCommander.Builder builder = JCommander.newBuilder().addObject(argsObj);
|
||||||
|
builder.acceptUnknownOptions(true); // workaround for "default" command
|
||||||
|
JadxCLICommands.append(builder);
|
||||||
|
this.jc = builder.build();
|
||||||
|
this.argsObj = argsObj;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean parse(String[] args) {
|
public boolean parse(String[] args) {
|
||||||
@@ -43,7 +50,15 @@ public class JCommanderWrapper<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void overrideProvided(T obj) {
|
public boolean processCommands() {
|
||||||
|
String parsedCommand = jc.getParsedCommand();
|
||||||
|
if (parsedCommand == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return JadxCLICommands.process(this, jc, parsedCommand);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void overrideProvided(JadxCLIArgs obj) {
|
||||||
List<ParameterDescription> fieldsParams = jc.getParameters();
|
List<ParameterDescription> fieldsParams = jc.getParameters();
|
||||||
List<ParameterDescription> parameters = new ArrayList<>(1 + fieldsParams.size());
|
List<ParameterDescription> parameters = new ArrayList<>(1 + fieldsParams.size());
|
||||||
parameters.add(jc.getMainParameterValue());
|
parameters.add(jc.getMainParameterValue());
|
||||||
@@ -70,13 +85,49 @@ public class JCommanderWrapper<T> {
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<String> getUnknownOptions() {
|
||||||
|
return jc.getUnknownOptions();
|
||||||
|
}
|
||||||
|
|
||||||
public void printUsage() {
|
public void printUsage() {
|
||||||
// print usage in not sorted fields order (by default its sorted by description)
|
LogHelper.setLogLevel(LogHelper.LogLevelEnum.ERROR); // mute logger while printing help
|
||||||
|
|
||||||
|
// print usage in not sorted fields order (by default sorted by description)
|
||||||
PrintStream out = System.out;
|
PrintStream out = System.out;
|
||||||
out.println();
|
out.println();
|
||||||
out.println("jadx - dex to java decompiler, version: " + JadxDecompiler.getVersion());
|
out.println("jadx - dex to java decompiler, version: " + JadxDecompiler.getVersion());
|
||||||
out.println();
|
out.println();
|
||||||
out.println("usage: jadx [options] " + jc.getMainParameterDescription());
|
out.println("usage: jadx [command] [options] " + jc.getMainParameterDescription());
|
||||||
|
|
||||||
|
out.println("commands (use '<command> --help' for command options):");
|
||||||
|
for (String command : jc.getCommands().keySet()) {
|
||||||
|
out.println(" " + command + "\t - " + jc.getUsageFormatter().getCommandDescription(command));
|
||||||
|
}
|
||||||
|
out.println();
|
||||||
|
|
||||||
|
int maxNamesLen = printOptions(jc, out, true);
|
||||||
|
out.println(appendPluginOptions(maxNamesLen));
|
||||||
|
out.println();
|
||||||
|
out.println("Environment variables:");
|
||||||
|
out.println(" JADX_DISABLE_ZIP_SECURITY - set to 'true' to disable all security checks for zip files");
|
||||||
|
out.println(" JADX_ZIP_MAX_ENTRIES_COUNT - maximum allowed number of entries in zip files (default: 100 000)");
|
||||||
|
out.println(" JADX_TMP_DIR - custom temp directory, using system by default");
|
||||||
|
out.println();
|
||||||
|
out.println("Examples:");
|
||||||
|
out.println(" jadx -d out classes.dex");
|
||||||
|
out.println(" jadx --rename-flags \"none\" classes.dex");
|
||||||
|
out.println(" jadx --rename-flags \"valid, printable\" classes.dex");
|
||||||
|
out.println(" jadx --log-level ERROR app.apk");
|
||||||
|
out.println(" jadx -Pdex-input.verify-checksum=no app.apk");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void printUsage(JCommander subCommander) {
|
||||||
|
PrintStream out = System.out;
|
||||||
|
out.println("usage: " + subCommander.getProgramName() + " [options]");
|
||||||
|
printOptions(subCommander, out, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int printOptions(JCommander jc, PrintStream out, boolean addDefaults) {
|
||||||
out.println("options:");
|
out.println("options:");
|
||||||
|
|
||||||
List<ParameterDescription> params = jc.getParameters();
|
List<ParameterDescription> params = jc.getParameters();
|
||||||
@@ -91,7 +142,7 @@ public class JCommanderWrapper<T> {
|
|||||||
}
|
}
|
||||||
maxNamesLen += 3;
|
maxNamesLen += 3;
|
||||||
|
|
||||||
JadxCLIArgs args = (JadxCLIArgs) jc.getObjects().get(0);
|
Object args = jc.getObjects().get(0);
|
||||||
for (Field f : getFields(args.getClass())) {
|
for (Field f : getFields(args.getClass())) {
|
||||||
String name = f.getName();
|
String name = f.getName();
|
||||||
ParameterDescription p = paramsMap.get(name);
|
ParameterDescription p = paramsMap.get(name);
|
||||||
@@ -113,26 +164,21 @@ public class JCommanderWrapper<T> {
|
|||||||
} else {
|
} else {
|
||||||
opt.append("- ").append(description);
|
opt.append("- ").append(description);
|
||||||
}
|
}
|
||||||
String defaultValue = getDefaultValue(args, f, opt);
|
if (addDefaults) {
|
||||||
if (defaultValue != null && !description.contains("(default)")) {
|
String defaultValue = getDefaultValue(args, f, opt);
|
||||||
opt.append(", default: ").append(defaultValue);
|
if (defaultValue != null && !description.contains("(default)")) {
|
||||||
|
opt.append(", default: ").append(defaultValue);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
out.println(opt);
|
out.println(opt);
|
||||||
}
|
}
|
||||||
out.println(appendPluginOptions(maxNamesLen));
|
return maxNamesLen;
|
||||||
out.println();
|
|
||||||
out.println("Examples:");
|
|
||||||
out.println(" jadx -d out classes.dex");
|
|
||||||
out.println(" jadx --rename-flags \"none\" classes.dex");
|
|
||||||
out.println(" jadx --rename-flags \"valid, printable\" classes.dex");
|
|
||||||
out.println(" jadx --log-level ERROR app.apk");
|
|
||||||
out.println(" jadx -Pdex-input.verify-checksum=no app.apk");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all declared fields of the specified class and all super classes
|
* Get all declared fields of the specified class and all super classes
|
||||||
*/
|
*/
|
||||||
private List<Field> getFields(Class<?> clazz) {
|
private static List<Field> getFields(Class<?> clazz) {
|
||||||
List<Field> fieldList = new ArrayList<>();
|
List<Field> fieldList = new ArrayList<>();
|
||||||
while (clazz != null) {
|
while (clazz != null) {
|
||||||
fieldList.addAll(Arrays.asList(clazz.getDeclaredFields()));
|
fieldList.addAll(Arrays.asList(clazz.getDeclaredFields()));
|
||||||
@@ -142,7 +188,7 @@ public class JCommanderWrapper<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private String getDefaultValue(JadxCLIArgs args, Field f, StringBuilder opt) {
|
private static String getDefaultValue(Object args, Field f, StringBuilder opt) {
|
||||||
try {
|
try {
|
||||||
Class<?> fieldType = f.getType();
|
Class<?> fieldType = f.getType();
|
||||||
if (fieldType == int.class) {
|
if (fieldType == int.class) {
|
||||||
@@ -171,13 +217,18 @@ public class JCommanderWrapper<T> {
|
|||||||
|
|
||||||
private String appendPluginOptions(int maxNamesLen) {
|
private String appendPluginOptions(int maxNamesLen) {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
JadxPluginManager pluginManager = new JadxPluginManager();
|
|
||||||
pluginManager.load();
|
|
||||||
int k = 1;
|
int k = 1;
|
||||||
for (JadxPlugin plugin : pluginManager.getAllPlugins()) {
|
// load and init all options plugins to print all options
|
||||||
if (plugin instanceof JadxPluginOptions) {
|
try (JadxDecompiler decompiler = new JadxDecompiler(new JadxArgs())) {
|
||||||
if (appendPlugin(((JadxPluginOptions) plugin), sb, maxNamesLen, k)) {
|
JadxPluginManager pluginManager = decompiler.getPluginManager();
|
||||||
k++;
|
pluginManager.load(new JadxExternalPluginsLoader());
|
||||||
|
pluginManager.initAll();
|
||||||
|
for (PluginContext context : pluginManager.getAllPluginContexts()) {
|
||||||
|
JadxPluginOptions options = context.getOptions();
|
||||||
|
if (options != null) {
|
||||||
|
if (appendPlugin(context.getPluginInfo(), context.getOptions(), sb, maxNamesLen, k)) {
|
||||||
|
k++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -187,12 +238,11 @@ public class JCommanderWrapper<T> {
|
|||||||
return "\nPlugin options (-P<name>=<value>):" + sb;
|
return "\nPlugin options (-P<name>=<value>):" + sb;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean appendPlugin(JadxPluginOptions plugin, StringBuilder out, int maxNamesLen, int k) {
|
private boolean appendPlugin(JadxPluginInfo pluginInfo, JadxPluginOptions options, StringBuilder out, int maxNamesLen, int k) {
|
||||||
List<OptionDescription> descs = plugin.getOptionsDescriptions();
|
List<OptionDescription> descs = options.getOptionsDescriptions();
|
||||||
if (descs.isEmpty()) {
|
if (descs.isEmpty()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
JadxPluginInfo pluginInfo = plugin.getPluginInfo();
|
|
||||||
out.append("\n ").append(k).append(") ");
|
out.append("\n ").append(k).append(") ");
|
||||||
out.append(pluginInfo.getPluginId()).append(": ").append(pluginInfo.getDescription());
|
out.append(pluginInfo.getPluginId()).append(": ").append(pluginInfo.getDescription());
|
||||||
for (OptionDescription desc : descs) {
|
for (OptionDescription desc : descs) {
|
||||||
|
|||||||
@@ -5,11 +5,13 @@ import org.slf4j.LoggerFactory;
|
|||||||
|
|
||||||
import jadx.api.JadxArgs;
|
import jadx.api.JadxArgs;
|
||||||
import jadx.api.JadxDecompiler;
|
import jadx.api.JadxDecompiler;
|
||||||
|
import jadx.api.impl.AnnotatedCodeWriter;
|
||||||
import jadx.api.impl.NoOpCodeCache;
|
import jadx.api.impl.NoOpCodeCache;
|
||||||
import jadx.api.impl.SimpleCodeWriter;
|
import jadx.api.impl.SimpleCodeWriter;
|
||||||
import jadx.cli.LogHelper.LogLevelEnum;
|
import jadx.cli.LogHelper.LogLevelEnum;
|
||||||
import jadx.core.utils.exceptions.JadxArgsValidateException;
|
import jadx.core.utils.exceptions.JadxArgsValidateException;
|
||||||
import jadx.core.utils.files.FileUtils;
|
import jadx.core.utils.files.FileUtils;
|
||||||
|
import jadx.plugins.tools.JadxExternalPluginsLoader;
|
||||||
|
|
||||||
public class JadxCLI {
|
public class JadxCLI {
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(JadxCLI.class);
|
private static final Logger LOG = LoggerFactory.getLogger(JadxCLI.class);
|
||||||
@@ -43,7 +45,8 @@ public class JadxCLI {
|
|||||||
LogHelper.setLogLevelsForLoadingStage();
|
LogHelper.setLogLevelsForLoadingStage();
|
||||||
JadxArgs jadxArgs = cliArgs.toJadxArgs();
|
JadxArgs jadxArgs = cliArgs.toJadxArgs();
|
||||||
jadxArgs.setCodeCache(new NoOpCodeCache());
|
jadxArgs.setCodeCache(new NoOpCodeCache());
|
||||||
jadxArgs.setCodeWriterProvider(SimpleCodeWriter::new);
|
jadxArgs.setPluginLoader(new JadxExternalPluginsLoader());
|
||||||
|
initCodeWriterProvider(jadxArgs);
|
||||||
try (JadxDecompiler jadx = new JadxDecompiler(jadxArgs)) {
|
try (JadxDecompiler jadx = new JadxDecompiler(jadxArgs)) {
|
||||||
jadx.load();
|
jadx.load();
|
||||||
if (checkForErrors(jadx)) {
|
if (checkForErrors(jadx)) {
|
||||||
@@ -64,6 +67,18 @@ public class JadxCLI {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void initCodeWriterProvider(JadxArgs jadxArgs) {
|
||||||
|
switch (jadxArgs.getOutputFormat()) {
|
||||||
|
case JAVA:
|
||||||
|
jadxArgs.setCodeWriterProvider(SimpleCodeWriter::new);
|
||||||
|
break;
|
||||||
|
case JSON:
|
||||||
|
// needed for code offsets and source lines
|
||||||
|
jadxArgs.setCodeWriterProvider(AnnotatedCodeWriter::new);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static boolean checkForErrors(JadxDecompiler jadx) {
|
private static boolean checkForErrors(JadxDecompiler jadx) {
|
||||||
if (jadx.getRoot().getClasses().isEmpty()) {
|
if (jadx.getRoot().getClasses().isEmpty()) {
|
||||||
if (jadx.getArgs().isSkipResources()) {
|
if (jadx.getArgs().isSkipResources()) {
|
||||||
@@ -87,6 +102,7 @@ public class JadxCLI {
|
|||||||
if (LogHelper.getLogLevel() == LogLevelEnum.QUIET) {
|
if (LogHelper.getLogLevel() == LogLevelEnum.QUIET) {
|
||||||
jadx.save();
|
jadx.save();
|
||||||
} else {
|
} else {
|
||||||
|
LOG.info("processing ...");
|
||||||
jadx.save(500, (done, total) -> {
|
jadx.save(500, (done, total) -> {
|
||||||
int progress = (int) (done * 100.0 / total);
|
int progress = (int) (done * 100.0 / total);
|
||||||
System.out.printf("INFO - progress: %d of %d (%d%%)\r", done, total, progress);
|
System.out.printf("INFO - progress: %d of %d (%d%%)\r", done, total, progress);
|
||||||
|
|||||||
@@ -1,12 +1,16 @@
|
|||||||
package jadx.cli;
|
package jadx.cli;
|
||||||
|
|
||||||
|
import java.nio.file.Path;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.function.Supplier;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
@@ -20,13 +24,17 @@ import jadx.api.JadxArgs;
|
|||||||
import jadx.api.JadxArgs.RenameEnum;
|
import jadx.api.JadxArgs.RenameEnum;
|
||||||
import jadx.api.JadxArgs.UseKotlinMethodsForVarNames;
|
import jadx.api.JadxArgs.UseKotlinMethodsForVarNames;
|
||||||
import jadx.api.JadxDecompiler;
|
import jadx.api.JadxDecompiler;
|
||||||
import jadx.api.args.DeobfuscationMapFileMode;
|
import jadx.api.args.GeneratedRenamesMappingFileMode;
|
||||||
|
import jadx.api.args.IntegerFormat;
|
||||||
|
import jadx.api.args.ResourceNameSource;
|
||||||
|
import jadx.api.args.UserRenamesMappingsMode;
|
||||||
|
import jadx.core.deobf.conditions.DeobfWhitelist;
|
||||||
import jadx.core.utils.exceptions.JadxException;
|
import jadx.core.utils.exceptions.JadxException;
|
||||||
import jadx.core.utils.files.FileUtils;
|
import jadx.core.utils.files.FileUtils;
|
||||||
|
|
||||||
public class JadxCLIArgs {
|
public class JadxCLIArgs {
|
||||||
|
|
||||||
@Parameter(description = "<input files> (.apk, .dex, .jar, .class, .smali, .zip, .aar, .arsc, .aab)")
|
@Parameter(description = "<input files> (.apk, .dex, .jar, .class, .smali, .zip, .aar, .arsc, .aab, .xapk)")
|
||||||
protected List<String> files = new ArrayList<>(1);
|
protected List<String> files = new ArrayList<>(1);
|
||||||
|
|
||||||
@Parameter(names = { "-d", "--output-dir" }, description = "output directory")
|
@Parameter(names = { "-d", "--output-dir" }, description = "output directory")
|
||||||
@@ -73,10 +81,13 @@ public class JadxCLIArgs {
|
|||||||
@Parameter(names = { "--show-bad-code" }, description = "show inconsistent code (incorrectly decompiled)")
|
@Parameter(names = { "--show-bad-code" }, description = "show inconsistent code (incorrectly decompiled)")
|
||||||
protected boolean showInconsistentCode = false;
|
protected boolean showInconsistentCode = false;
|
||||||
|
|
||||||
|
@Parameter(names = { "--no-xml-pretty-print" }, description = "do not prettify XML")
|
||||||
|
protected boolean skipXmlPrettyPrint = false;
|
||||||
|
|
||||||
@Parameter(names = { "--no-imports" }, description = "disable use of imports, always write entire package name")
|
@Parameter(names = { "--no-imports" }, description = "disable use of imports, always write entire package name")
|
||||||
protected boolean useImports = true;
|
protected boolean useImports = true;
|
||||||
|
|
||||||
@Parameter(names = { "--no-debug-info" }, description = "disable debug info")
|
@Parameter(names = { "--no-debug-info" }, description = "disable debug info parsing and processing")
|
||||||
protected boolean debugInfo = true;
|
protected boolean debugInfo = true;
|
||||||
|
|
||||||
@Parameter(names = { "--add-debug-lines" }, description = "add comments with debug line numbers if available")
|
@Parameter(names = { "--add-debug-lines" }, description = "add comments with debug line numbers if available")
|
||||||
@@ -88,6 +99,15 @@ public class JadxCLIArgs {
|
|||||||
@Parameter(names = { "--no-inline-methods" }, description = "disable methods inline")
|
@Parameter(names = { "--no-inline-methods" }, description = "disable methods inline")
|
||||||
protected boolean inlineMethods = true;
|
protected boolean inlineMethods = true;
|
||||||
|
|
||||||
|
@Parameter(names = { "--no-move-inner-classes" }, description = "disable move inner classes into parent")
|
||||||
|
protected boolean moveInnerClasses = true;
|
||||||
|
|
||||||
|
@Parameter(names = { "--no-inline-kotlin-lambda" }, description = "disable inline for Kotlin lambdas")
|
||||||
|
protected boolean allowInlineKotlinLambda = true;
|
||||||
|
|
||||||
|
@Parameter(names = "--no-finally", description = "don't extract finally block")
|
||||||
|
protected boolean extractFinally = true;
|
||||||
|
|
||||||
@Parameter(names = "--no-replace-consts", description = "don't replace constant value with matching constant field")
|
@Parameter(names = "--no-replace-consts", description = "don't replace constant value with matching constant field")
|
||||||
protected boolean replaceConsts = true;
|
protected boolean replaceConsts = true;
|
||||||
|
|
||||||
@@ -97,6 +117,22 @@ public class JadxCLIArgs {
|
|||||||
@Parameter(names = { "--respect-bytecode-access-modifiers" }, description = "don't change original access modifiers")
|
@Parameter(names = { "--respect-bytecode-access-modifiers" }, description = "don't change original access modifiers")
|
||||||
protected boolean respectBytecodeAccessModifiers = false;
|
protected boolean respectBytecodeAccessModifiers = false;
|
||||||
|
|
||||||
|
@Parameter(
|
||||||
|
names = { "--mappings-path" },
|
||||||
|
description = "deobfuscation mappings file or directory. Allowed formats: Tiny and Tiny v2 (both '.tiny'), Enigma (.mapping) or Enigma directory"
|
||||||
|
)
|
||||||
|
protected Path userRenamesMappingsPath;
|
||||||
|
|
||||||
|
@Parameter(
|
||||||
|
names = { "--mappings-mode" },
|
||||||
|
description = "set mode for handling the deobfuscation mapping file:"
|
||||||
|
+ "\n 'read' - just read, user can always save manually (default)"
|
||||||
|
+ "\n 'read-and-autosave-every-change' - read and autosave after every change"
|
||||||
|
+ "\n 'read-and-autosave-before-closing' - read and autosave before exiting the app or closing the project"
|
||||||
|
+ "\n 'ignore' - don't read or save (can be used to skip loading mapping files referenced in the project file)"
|
||||||
|
)
|
||||||
|
protected UserRenamesMappingsMode userRenamesMappingsMode = UserRenamesMappingsMode.getDefault();
|
||||||
|
|
||||||
@Parameter(names = { "--deobf" }, description = "activate deobfuscation")
|
@Parameter(names = { "--deobf" }, description = "activate deobfuscation")
|
||||||
protected boolean deobfuscationOn = false;
|
protected boolean deobfuscationOn = false;
|
||||||
|
|
||||||
@@ -107,27 +143,41 @@ public class JadxCLIArgs {
|
|||||||
protected int deobfuscationMaxLength = 64;
|
protected int deobfuscationMaxLength = 64;
|
||||||
|
|
||||||
@Parameter(
|
@Parameter(
|
||||||
names = { "--deobf-cfg-file" },
|
names = { "--deobf-whitelist" },
|
||||||
description = "deobfuscation map file, default: same dir and name as input file with '.jobf' extension"
|
description = "space separated list of classes (full name) and packages (ends with '.*') to exclude from deobfuscation"
|
||||||
)
|
)
|
||||||
protected String deobfuscationMapFile;
|
protected String deobfuscationWhitelistStr = DeobfWhitelist.DEFAULT_STR;
|
||||||
|
|
||||||
|
@Parameter(
|
||||||
|
names = { "--deobf-cfg-file" },
|
||||||
|
description = "deobfuscation mappings file used for JADX auto-generated names (in the JOBF file format),"
|
||||||
|
+ " default: same dir and name as input file with '.jobf' extension"
|
||||||
|
)
|
||||||
|
protected String generatedRenamesMappingFile;
|
||||||
|
|
||||||
@Parameter(
|
@Parameter(
|
||||||
names = { "--deobf-cfg-file-mode" },
|
names = { "--deobf-cfg-file-mode" },
|
||||||
description = "set mode for handle deobfuscation map file:"
|
description = "set mode for handling the JADX auto-generated names' deobfuscation map file:"
|
||||||
+ "\n 'read' - read if found, don't save (default)"
|
+ "\n 'read' - read if found, don't save (default)"
|
||||||
+ "\n 'read-or-save' - read if found, save otherwise (don't overwrite)"
|
+ "\n 'read-or-save' - read if found, save otherwise (don't overwrite)"
|
||||||
+ "\n 'overwrite' - don't read, always save"
|
+ "\n 'overwrite' - don't read, always save"
|
||||||
+ "\n 'ignore' - don't read and don't save",
|
+ "\n 'ignore' - don't read and don't save",
|
||||||
converter = DeobfuscationMapFileModeConverter.class
|
converter = DeobfuscationMapFileModeConverter.class
|
||||||
)
|
)
|
||||||
protected DeobfuscationMapFileMode deobfuscationMapFileMode = DeobfuscationMapFileMode.READ;
|
protected GeneratedRenamesMappingFileMode generatedRenamesMappingFileMode = GeneratedRenamesMappingFileMode.getDefault();
|
||||||
|
|
||||||
@Parameter(names = { "--deobf-use-sourcename" }, description = "use source file name as class name alias")
|
@Parameter(names = { "--deobf-use-sourcename" }, description = "use source file name as class name alias")
|
||||||
protected boolean deobfuscationUseSourceNameAsAlias = false;
|
protected boolean deobfuscationUseSourceNameAsAlias = false;
|
||||||
|
|
||||||
@Parameter(names = { "--deobf-parse-kotlin-metadata" }, description = "parse kotlin metadata to class and package names")
|
@Parameter(
|
||||||
protected boolean deobfuscationParseKotlinMetadata = false;
|
names = { "--deobf-res-name-source" },
|
||||||
|
description = "better name source for resources:"
|
||||||
|
+ "\n 'auto' - automatically select best name (default)"
|
||||||
|
+ "\n 'resources' - use resources names"
|
||||||
|
+ "\n 'code' - use R class fields names",
|
||||||
|
converter = ResourceNameSourceConverter.class
|
||||||
|
)
|
||||||
|
protected ResourceNameSource resourceNameSource = ResourceNameSource.AUTO;
|
||||||
|
|
||||||
@Parameter(
|
@Parameter(
|
||||||
names = { "--use-kotlin-methods-for-var-names" },
|
names = { "--use-kotlin-methods-for-var-names" },
|
||||||
@@ -148,6 +198,16 @@ public class JadxCLIArgs {
|
|||||||
)
|
)
|
||||||
protected Set<RenameEnum> renameFlags = EnumSet.allOf(RenameEnum.class);
|
protected Set<RenameEnum> renameFlags = EnumSet.allOf(RenameEnum.class);
|
||||||
|
|
||||||
|
@Parameter(
|
||||||
|
names = { "--integer-format" },
|
||||||
|
description = "how integers are displayed:"
|
||||||
|
+ "\n 'auto' - automatically select (default)"
|
||||||
|
+ "\n 'decimal' - use decimal"
|
||||||
|
+ "\n 'hexadecimal' - use hexadecimal",
|
||||||
|
converter = IntegerFormatConverter.class
|
||||||
|
)
|
||||||
|
protected IntegerFormat integerFormat = IntegerFormat.AUTO;
|
||||||
|
|
||||||
@Parameter(names = { "--fs-case-sensitive" }, description = "treat filesystem as case sensitive, false by default")
|
@Parameter(names = { "--fs-case-sensitive" }, description = "treat filesystem as case sensitive, false by default")
|
||||||
protected boolean fsCaseSensitive = false;
|
protected boolean fsCaseSensitive = false;
|
||||||
|
|
||||||
@@ -173,7 +233,7 @@ public class JadxCLIArgs {
|
|||||||
@Parameter(
|
@Parameter(
|
||||||
names = { "--log-level" },
|
names = { "--log-level" },
|
||||||
description = "set log level, values: quiet, progress, error, warn, info, debug",
|
description = "set log level, values: quiet, progress, error, warn, info, debug",
|
||||||
converter = LogHelper.LogLevelConverter.class
|
converter = LogLevelConverter.class
|
||||||
)
|
)
|
||||||
protected LogHelper.LogLevelEnum logLevel = LogHelper.LogLevelEnum.PROGRESS;
|
protected LogHelper.LogLevelEnum logLevel = LogHelper.LogLevelEnum.PROGRESS;
|
||||||
|
|
||||||
@@ -215,6 +275,10 @@ public class JadxCLIArgs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean process(JCommanderWrapper<JadxCLIArgs> jcw) {
|
private boolean process(JCommanderWrapper<JadxCLIArgs> jcw) {
|
||||||
|
files.addAll(jcw.getUnknownOptions());
|
||||||
|
if (jcw.processCommands()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (printHelp) {
|
if (printHelp) {
|
||||||
jcw.printUsage();
|
jcw.printUsage();
|
||||||
return false;
|
return false;
|
||||||
@@ -254,25 +318,35 @@ public class JadxCLIArgs {
|
|||||||
args.setCfgOutput(cfgOutput);
|
args.setCfgOutput(cfgOutput);
|
||||||
args.setRawCFGOutput(rawCfgOutput);
|
args.setRawCFGOutput(rawCfgOutput);
|
||||||
args.setReplaceConsts(replaceConsts);
|
args.setReplaceConsts(replaceConsts);
|
||||||
|
if (userRenamesMappingsPath != null) {
|
||||||
|
args.setUserRenamesMappingsPath(userRenamesMappingsPath);
|
||||||
|
}
|
||||||
|
args.setUserRenamesMappingsMode(userRenamesMappingsMode);
|
||||||
args.setDeobfuscationOn(deobfuscationOn);
|
args.setDeobfuscationOn(deobfuscationOn);
|
||||||
args.setDeobfuscationMapFile(FileUtils.toFile(deobfuscationMapFile));
|
args.setGeneratedRenamesMappingFile(FileUtils.toFile(generatedRenamesMappingFile));
|
||||||
args.setDeobfuscationMapFileMode(deobfuscationMapFileMode);
|
args.setGeneratedRenamesMappingFileMode(generatedRenamesMappingFileMode);
|
||||||
args.setDeobfuscationMinLength(deobfuscationMinLength);
|
args.setDeobfuscationMinLength(deobfuscationMinLength);
|
||||||
args.setDeobfuscationMaxLength(deobfuscationMaxLength);
|
args.setDeobfuscationMaxLength(deobfuscationMaxLength);
|
||||||
|
args.setDeobfuscationWhitelist(Arrays.asList(deobfuscationWhitelistStr.split(" ")));
|
||||||
args.setUseSourceNameAsClassAlias(deobfuscationUseSourceNameAsAlias);
|
args.setUseSourceNameAsClassAlias(deobfuscationUseSourceNameAsAlias);
|
||||||
args.setParseKotlinMetadata(deobfuscationParseKotlinMetadata);
|
|
||||||
args.setUseKotlinMethodsForVarNames(useKotlinMethodsForVarNames);
|
args.setUseKotlinMethodsForVarNames(useKotlinMethodsForVarNames);
|
||||||
|
args.setResourceNameSource(resourceNameSource);
|
||||||
args.setEscapeUnicode(escapeUnicode);
|
args.setEscapeUnicode(escapeUnicode);
|
||||||
args.setRespectBytecodeAccModifiers(respectBytecodeAccessModifiers);
|
args.setRespectBytecodeAccModifiers(respectBytecodeAccessModifiers);
|
||||||
args.setExportAsGradleProject(exportAsGradleProject);
|
args.setExportAsGradleProject(exportAsGradleProject);
|
||||||
|
args.setSkipXmlPrettyPrint(skipXmlPrettyPrint);
|
||||||
args.setUseImports(useImports);
|
args.setUseImports(useImports);
|
||||||
args.setDebugInfo(debugInfo);
|
args.setDebugInfo(debugInfo);
|
||||||
args.setInsertDebugLines(addDebugLines);
|
args.setInsertDebugLines(addDebugLines);
|
||||||
args.setInlineAnonymousClasses(inlineAnonymousClasses);
|
args.setInlineAnonymousClasses(inlineAnonymousClasses);
|
||||||
args.setInlineMethods(inlineMethods);
|
args.setInlineMethods(inlineMethods);
|
||||||
|
args.setMoveInnerClasses(moveInnerClasses);
|
||||||
|
args.setAllowInlineKotlinLambda(allowInlineKotlinLambda);
|
||||||
|
args.setExtractFinally(extractFinally);
|
||||||
args.setRenameFlags(renameFlags);
|
args.setRenameFlags(renameFlags);
|
||||||
args.setFsCaseSensitive(fsCaseSensitive);
|
args.setFsCaseSensitive(fsCaseSensitive);
|
||||||
args.setCommentsLevel(commentsLevel);
|
args.setCommentsLevel(commentsLevel);
|
||||||
|
args.setIntegerFormat(integerFormat);
|
||||||
args.setUseDxInput(useDx);
|
args.setUseDxInput(useDx);
|
||||||
args.setPluginOptions(pluginOptions);
|
args.setPluginOptions(pluginOptions);
|
||||||
return args;
|
return args;
|
||||||
@@ -350,6 +424,26 @@ public class JadxCLIArgs {
|
|||||||
return inlineMethods;
|
return inlineMethods;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isMoveInnerClasses() {
|
||||||
|
return moveInnerClasses;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAllowInlineKotlinLambda() {
|
||||||
|
return allowInlineKotlinLambda;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isExtractFinally() {
|
||||||
|
return extractFinally;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Path getUserRenamesMappingsPath() {
|
||||||
|
return userRenamesMappingsPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserRenamesMappingsMode getUserRenamesMappingsMode() {
|
||||||
|
return userRenamesMappingsMode;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isDeobfuscationOn() {
|
public boolean isDeobfuscationOn() {
|
||||||
return deobfuscationOn;
|
return deobfuscationOn;
|
||||||
}
|
}
|
||||||
@@ -362,26 +456,34 @@ public class JadxCLIArgs {
|
|||||||
return deobfuscationMaxLength;
|
return deobfuscationMaxLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getDeobfuscationMapFile() {
|
public String getDeobfuscationWhitelistStr() {
|
||||||
return deobfuscationMapFile;
|
return deobfuscationWhitelistStr;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DeobfuscationMapFileMode getDeobfuscationMapFileMode() {
|
public String getGeneratedRenamesMappingFile() {
|
||||||
return deobfuscationMapFileMode;
|
return generatedRenamesMappingFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GeneratedRenamesMappingFileMode getGeneratedRenamesMappingFileMode() {
|
||||||
|
return generatedRenamesMappingFileMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isDeobfuscationUseSourceNameAsAlias() {
|
public boolean isDeobfuscationUseSourceNameAsAlias() {
|
||||||
return deobfuscationUseSourceNameAsAlias;
|
return deobfuscationUseSourceNameAsAlias;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isDeobfuscationParseKotlinMetadata() {
|
public ResourceNameSource getResourceNameSource() {
|
||||||
return deobfuscationParseKotlinMetadata;
|
return resourceNameSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
public UseKotlinMethodsForVarNames getUseKotlinMethodsForVarNames() {
|
public UseKotlinMethodsForVarNames getUseKotlinMethodsForVarNames() {
|
||||||
return useKotlinMethodsForVarNames;
|
return useKotlinMethodsForVarNames;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IntegerFormat getIntegerFormat() {
|
||||||
|
return integerFormat;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isEscapeUnicode() {
|
public boolean isEscapeUnicode() {
|
||||||
return escapeUnicode;
|
return escapeUnicode;
|
||||||
}
|
}
|
||||||
@@ -406,6 +508,10 @@ public class JadxCLIArgs {
|
|||||||
return exportAsGradleProject;
|
return exportAsGradleProject;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isSkipXmlPrettyPrint() {
|
||||||
|
return skipXmlPrettyPrint;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isRenameCaseSensitive() {
|
public boolean isRenameCaseSensitive() {
|
||||||
return renameFlags.contains(RenameEnum.CASE);
|
return renameFlags.contains(RenameEnum.CASE);
|
||||||
}
|
}
|
||||||
@@ -463,54 +569,64 @@ public class JadxCLIArgs {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class CommentsLevelConverter implements IStringConverter<CommentsLevel> {
|
public static class CommentsLevelConverter extends BaseEnumConverter<CommentsLevel> {
|
||||||
@Override
|
public CommentsLevelConverter() {
|
||||||
public CommentsLevel convert(String value) {
|
super(CommentsLevel::valueOf, CommentsLevel::values);
|
||||||
try {
|
|
||||||
return CommentsLevel.valueOf(value.toUpperCase());
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
'\'' + value + "' is unknown comments level, possible values are: "
|
|
||||||
+ JadxCLIArgs.enumValuesString(CommentsLevel.values()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class UseKotlinMethodsForVarNamesConverter implements IStringConverter<UseKotlinMethodsForVarNames> {
|
public static class UseKotlinMethodsForVarNamesConverter extends BaseEnumConverter<UseKotlinMethodsForVarNames> {
|
||||||
@Override
|
public UseKotlinMethodsForVarNamesConverter() {
|
||||||
public UseKotlinMethodsForVarNames convert(String value) {
|
super(UseKotlinMethodsForVarNames::valueOf, UseKotlinMethodsForVarNames::values);
|
||||||
try {
|
|
||||||
return UseKotlinMethodsForVarNames.valueOf(value.replace('-', '_').toUpperCase());
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
'\'' + value + "' is unknown, possible values are: "
|
|
||||||
+ JadxCLIArgs.enumValuesString(CommentsLevel.values()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class DeobfuscationMapFileModeConverter implements IStringConverter<DeobfuscationMapFileMode> {
|
public static class DeobfuscationMapFileModeConverter extends BaseEnumConverter<GeneratedRenamesMappingFileMode> {
|
||||||
@Override
|
public DeobfuscationMapFileModeConverter() {
|
||||||
public DeobfuscationMapFileMode convert(String value) {
|
super(GeneratedRenamesMappingFileMode::valueOf, GeneratedRenamesMappingFileMode::values);
|
||||||
try {
|
|
||||||
return DeobfuscationMapFileMode.valueOf(value.toUpperCase());
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
'\'' + value + "' is unknown, possible values are: "
|
|
||||||
+ JadxCLIArgs.enumValuesString(DeobfuscationMapFileMode.values()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class DecompilationModeConverter implements IStringConverter<DecompilationMode> {
|
public static class ResourceNameSourceConverter extends BaseEnumConverter<ResourceNameSource> {
|
||||||
|
public ResourceNameSourceConverter() {
|
||||||
|
super(ResourceNameSource::valueOf, ResourceNameSource::values);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class DecompilationModeConverter extends BaseEnumConverter<DecompilationMode> {
|
||||||
|
public DecompilationModeConverter() {
|
||||||
|
super(DecompilationMode::valueOf, DecompilationMode::values);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class LogLevelConverter extends BaseEnumConverter<LogHelper.LogLevelEnum> {
|
||||||
|
public LogLevelConverter() {
|
||||||
|
super(LogHelper.LogLevelEnum::valueOf, LogHelper.LogLevelEnum::values);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class IntegerFormatConverter extends BaseEnumConverter<IntegerFormat> {
|
||||||
|
public IntegerFormatConverter() {
|
||||||
|
super(IntegerFormat::valueOf, IntegerFormat::values);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract static class BaseEnumConverter<E extends Enum<E>> implements IStringConverter<E> {
|
||||||
|
private final Function<String, E> parse;
|
||||||
|
private final Supplier<E[]> values;
|
||||||
|
|
||||||
|
public BaseEnumConverter(Function<String, E> parse, Supplier<E[]> values) {
|
||||||
|
this.parse = parse;
|
||||||
|
this.values = values;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DecompilationMode convert(String value) {
|
public E convert(String value) {
|
||||||
try {
|
try {
|
||||||
return DecompilationMode.valueOf(value.toUpperCase());
|
return parse.apply(stringAsEnumName(value));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
'\'' + value + "' is unknown, possible values are: "
|
'\'' + value + "' is unknown, possible values are: " + enumValuesString(values.get()));
|
||||||
+ JadxCLIArgs.enumValuesString(DecompilationMode.values()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -520,4 +636,9 @@ public class JadxCLIArgs {
|
|||||||
.map(v -> v.name().replace('_', '-').toLowerCase(Locale.ROOT))
|
.map(v -> v.name().replace('_', '-').toLowerCase(Locale.ROOT))
|
||||||
.collect(Collectors.joining(", "));
|
.collect(Collectors.joining(", "));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static String stringAsEnumName(String value) {
|
||||||
|
// inverse of enumValuesString conversion
|
||||||
|
return value.replace('-', '_').toUpperCase(Locale.ROOT);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package jadx.cli;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
|
||||||
|
import com.beust.jcommander.JCommander;
|
||||||
|
|
||||||
|
import jadx.cli.commands.CommandPlugins;
|
||||||
|
import jadx.cli.commands.ICommand;
|
||||||
|
|
||||||
|
public class JadxCLICommands {
|
||||||
|
private static final Map<String, ICommand> COMMANDS_MAP = new TreeMap<>();
|
||||||
|
|
||||||
|
static {
|
||||||
|
JadxCLICommands.register(new CommandPlugins());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void register(ICommand command) {
|
||||||
|
COMMANDS_MAP.put(command.name(), command);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void append(JCommander.Builder builder) {
|
||||||
|
COMMANDS_MAP.forEach(builder::addCommand);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean process(JCommanderWrapper<?> jcw, JCommander jc, String parsedCommand) {
|
||||||
|
ICommand command = COMMANDS_MAP.get(parsedCommand);
|
||||||
|
if (command == null) {
|
||||||
|
throw new IllegalArgumentException("Unknown command: " + parsedCommand);
|
||||||
|
}
|
||||||
|
JCommander subCommander = jc.getCommands().get(parsedCommand);
|
||||||
|
command.process(jcw, subCommander);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,8 +4,6 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import com.beust.jcommander.IStringConverter;
|
|
||||||
|
|
||||||
import ch.qos.logback.classic.Level;
|
import ch.qos.logback.classic.Level;
|
||||||
import ch.qos.logback.classic.Logger;
|
import ch.qos.logback.classic.Logger;
|
||||||
|
|
||||||
@@ -53,6 +51,11 @@ public class LogHelper {
|
|||||||
return args.logLevel;
|
return args.logLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void setLogLevel(LogLevelEnum newLogLevel) {
|
||||||
|
logLevelValue = newLogLevel;
|
||||||
|
applyLogLevel(logLevelValue);
|
||||||
|
}
|
||||||
|
|
||||||
public static void setLogLevelsForLoadingStage() {
|
public static void setLogLevelsForLoadingStage() {
|
||||||
if (logLevelValue == null) {
|
if (logLevelValue == null) {
|
||||||
return;
|
return;
|
||||||
@@ -119,18 +122,4 @@ public class LogHelper {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class LogLevelConverter implements IStringConverter<LogLevelEnum> {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public LogLevelEnum convert(String value) {
|
|
||||||
try {
|
|
||||||
return LogLevelEnum.valueOf(value.toUpperCase());
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
'\'' + value + "' is unknown log level, possible values are "
|
|
||||||
+ JadxCLIArgs.enumValuesString(LogLevelEnum.values()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ public class SingleClassMode {
|
|||||||
throw new JadxRuntimeException("Input class not found: " + singleClass);
|
throw new JadxRuntimeException("Input class not found: " + singleClass);
|
||||||
}
|
}
|
||||||
if (clsForProcess.contains(AFlag.DONT_GENERATE)) {
|
if (clsForProcess.contains(AFlag.DONT_GENERATE)) {
|
||||||
throw new JadxRuntimeException("Input class can't be saved by currect jadx settings (marked as DONT_GENERATE)");
|
throw new JadxRuntimeException("Input class can't be saved by current jadx settings (marked as DONT_GENERATE)");
|
||||||
}
|
}
|
||||||
if (clsForProcess.isInner()) {
|
if (clsForProcess.isInner()) {
|
||||||
clsForProcess = clsForProcess.getTopParentClass();
|
clsForProcess = clsForProcess.getTopParentClass();
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package jadx.cli.clst;
|
|||||||
|
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
@@ -12,13 +11,10 @@ import org.slf4j.Logger;
|
|||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import jadx.api.JadxArgs;
|
import jadx.api.JadxArgs;
|
||||||
import jadx.api.plugins.JadxPluginManager;
|
import jadx.api.JadxDecompiler;
|
||||||
import jadx.api.plugins.input.JadxInputPlugin;
|
|
||||||
import jadx.api.plugins.input.data.ILoadResult;
|
|
||||||
import jadx.core.clsp.ClsSet;
|
import jadx.core.clsp.ClsSet;
|
||||||
import jadx.core.dex.nodes.ClassNode;
|
|
||||||
import jadx.core.dex.nodes.RootNode;
|
import jadx.core.dex.nodes.RootNode;
|
||||||
import jadx.core.dex.visitors.SignatureProcessor;
|
import jadx.core.utils.files.FileUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility class for convert dex or jar to jadx classes set (.jcst)
|
* Utility class for convert dex or jar to jadx classes set (.jcst)
|
||||||
@@ -27,10 +23,15 @@ public class ConvertToClsSet {
|
|||||||
private static final Logger LOG = LoggerFactory.getLogger(ConvertToClsSet.class);
|
private static final Logger LOG = LoggerFactory.getLogger(ConvertToClsSet.class);
|
||||||
|
|
||||||
public static void usage() {
|
public static void usage() {
|
||||||
LOG.info("<output .jcst or .jar file> <several input dex or jar files> ");
|
LOG.info("<output .jcst file> <several input dex or jar files> ");
|
||||||
|
LOG.info("Arguments to update core.jcst: "
|
||||||
|
+ "<jadx root>/jadx-core/src/main/resources/clst/core.jcst "
|
||||||
|
+ "<sdk_root>/platforms/android-<api level>/android.jar"
|
||||||
|
+ "<sdk_root>/platforms/android-<api level>/optional/android.car.jar "
|
||||||
|
+ "<sdk_root>/platforms/android-<api level>/optional/org.apache.http.legacy.jar");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) {
|
||||||
if (args.length < 2) {
|
if (args.length < 2) {
|
||||||
usage();
|
usage();
|
||||||
System.exit(1);
|
System.exit(1);
|
||||||
@@ -38,30 +39,31 @@ public class ConvertToClsSet {
|
|||||||
List<Path> inputPaths = Stream.of(args).map(Paths::get).collect(Collectors.toList());
|
List<Path> inputPaths = Stream.of(args).map(Paths::get).collect(Collectors.toList());
|
||||||
Path output = inputPaths.remove(0);
|
Path output = inputPaths.remove(0);
|
||||||
|
|
||||||
JadxPluginManager pluginManager = new JadxPluginManager();
|
|
||||||
pluginManager.load();
|
|
||||||
List<ILoadResult> loadedInputs = new ArrayList<>();
|
|
||||||
for (JadxInputPlugin inputPlugin : pluginManager.getInputPlugins()) {
|
|
||||||
loadedInputs.add(inputPlugin.loadFiles(inputPaths));
|
|
||||||
}
|
|
||||||
|
|
||||||
JadxArgs jadxArgs = new JadxArgs();
|
JadxArgs jadxArgs = new JadxArgs();
|
||||||
|
jadxArgs.setInputFiles(FileUtils.toFiles(inputPaths));
|
||||||
|
|
||||||
|
// disable not needed passes executed at prepare stage
|
||||||
|
jadxArgs.setDeobfuscationOn(false);
|
||||||
jadxArgs.setRenameFlags(EnumSet.noneOf(JadxArgs.RenameEnum.class));
|
jadxArgs.setRenameFlags(EnumSet.noneOf(JadxArgs.RenameEnum.class));
|
||||||
RootNode root = new RootNode(jadxArgs);
|
jadxArgs.setUseSourceNameAsClassAlias(false);
|
||||||
root.loadClasses(loadedInputs);
|
jadxArgs.setMoveInnerClasses(false);
|
||||||
|
jadxArgs.setInlineAnonymousClasses(false);
|
||||||
|
jadxArgs.setInlineMethods(false);
|
||||||
|
|
||||||
// from pre-decompilation stage run only SignatureProcessor
|
// don't require/load class set file
|
||||||
SignatureProcessor signatureProcessor = new SignatureProcessor();
|
jadxArgs.setLoadJadxClsSetFile(false);
|
||||||
signatureProcessor.init(root);
|
|
||||||
for (ClassNode classNode : root.getClasses()) {
|
try (JadxDecompiler decompiler = new JadxDecompiler(jadxArgs)) {
|
||||||
signatureProcessor.visit(classNode);
|
decompiler.load();
|
||||||
|
RootNode root = decompiler.getRoot();
|
||||||
|
ClsSet set = new ClsSet(root);
|
||||||
|
set.loadFrom(root);
|
||||||
|
set.save(output);
|
||||||
|
|
||||||
|
LOG.info("Output: {}", output);
|
||||||
|
LOG.info("done");
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOG.error("Failed with error", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
ClsSet set = new ClsSet(root);
|
|
||||||
set.loadFrom(root);
|
|
||||||
set.save(output);
|
|
||||||
|
|
||||||
LOG.info("Output: {}", output);
|
|
||||||
LOG.info("done");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,98 @@
|
|||||||
|
package jadx.cli.commands;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.beust.jcommander.JCommander;
|
||||||
|
import com.beust.jcommander.Parameter;
|
||||||
|
import com.beust.jcommander.Parameters;
|
||||||
|
|
||||||
|
import jadx.cli.JCommanderWrapper;
|
||||||
|
import jadx.plugins.tools.JadxPluginsList;
|
||||||
|
import jadx.plugins.tools.JadxPluginsTools;
|
||||||
|
import jadx.plugins.tools.data.JadxPluginMetadata;
|
||||||
|
import jadx.plugins.tools.data.JadxPluginUpdate;
|
||||||
|
|
||||||
|
@Parameters(commandDescription = "manage jadx plugins")
|
||||||
|
public class CommandPlugins implements ICommand {
|
||||||
|
|
||||||
|
@Parameter(names = { "-i", "--install" }, description = "install plugin with locationId")
|
||||||
|
protected String install;
|
||||||
|
|
||||||
|
@Parameter(names = { "-j", "--install-jar" }, description = "install plugin from jar file")
|
||||||
|
protected String installJar;
|
||||||
|
|
||||||
|
@Parameter(names = { "-l", "--list" }, description = "list installed plugins")
|
||||||
|
protected boolean list;
|
||||||
|
|
||||||
|
@Parameter(names = { "-a", "--available" }, description = "list available plugins")
|
||||||
|
protected boolean available;
|
||||||
|
|
||||||
|
@Parameter(names = { "-u", "--update" }, description = "update installed plugins")
|
||||||
|
protected boolean update;
|
||||||
|
|
||||||
|
@Parameter(names = { "--uninstall" }, description = "uninstall plugin with pluginId")
|
||||||
|
protected String uninstall;
|
||||||
|
|
||||||
|
@Parameter(names = { "-h", "--help" }, description = "print this help", help = true)
|
||||||
|
protected boolean printHelp = false;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String name() {
|
||||||
|
return "plugins";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void process(JCommanderWrapper<?> jcw, JCommander subCommander) {
|
||||||
|
if (printHelp) {
|
||||||
|
jcw.printUsage(subCommander);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (install != null) {
|
||||||
|
installPlugin(install);
|
||||||
|
}
|
||||||
|
if (installJar != null) {
|
||||||
|
installPlugin("file:" + installJar);
|
||||||
|
}
|
||||||
|
if (uninstall != null) {
|
||||||
|
boolean uninstalled = JadxPluginsTools.getInstance().uninstall(uninstall);
|
||||||
|
System.out.println(uninstalled ? "Uninstalled" : "Plugin not found");
|
||||||
|
}
|
||||||
|
if (update) {
|
||||||
|
List<JadxPluginUpdate> updates = JadxPluginsTools.getInstance().updateAll();
|
||||||
|
if (updates.isEmpty()) {
|
||||||
|
System.out.println("No updates");
|
||||||
|
} else {
|
||||||
|
System.out.println("Installed updates: " + updates.size());
|
||||||
|
for (JadxPluginUpdate update : updates) {
|
||||||
|
System.out.println(" " + update.getPluginId() + ": " + update.getOldVersion() + " -> " + update.getNewVersion());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (list) {
|
||||||
|
List<JadxPluginMetadata> installed = JadxPluginsTools.getInstance().getInstalled();
|
||||||
|
System.out.println("Installed plugins: " + installed.size());
|
||||||
|
int i = 1;
|
||||||
|
for (JadxPluginMetadata plugin : installed) {
|
||||||
|
System.out.println(" " + (i++) + ") "
|
||||||
|
+ plugin.getPluginId() + " (" + plugin.getVersion() + ") - "
|
||||||
|
+ plugin.getName() + ": " + plugin.getDescription());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (available) {
|
||||||
|
List<JadxPluginMetadata> availableList = JadxPluginsList.getInstance().get();
|
||||||
|
System.out.println("Available plugins: " + availableList.size());
|
||||||
|
int i = 1;
|
||||||
|
for (JadxPluginMetadata plugin : availableList) {
|
||||||
|
System.out.println(" " + (i++) + ") "
|
||||||
|
+ plugin.getName() + ": " + plugin.getDescription()
|
||||||
|
+ " (" + plugin.getLocationId() + ")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void installPlugin(String locationId) {
|
||||||
|
JadxPluginMetadata plugin = JadxPluginsTools.getInstance().install(locationId);
|
||||||
|
System.out.println("Plugin installed: " + plugin.getPluginId() + ":" + plugin.getVersion());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package jadx.cli.commands;
|
||||||
|
|
||||||
|
import com.beust.jcommander.JCommander;
|
||||||
|
|
||||||
|
import jadx.cli.JCommanderWrapper;
|
||||||
|
|
||||||
|
public interface ICommand {
|
||||||
|
String name();
|
||||||
|
|
||||||
|
void process(JCommanderWrapper<?> jcw, JCommander subCommander);
|
||||||
|
}
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
<!-- Jadx logger config. Used both in cli and gui -->
|
||||||
|
|
||||||
<configuration>
|
<configuration>
|
||||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
<encoder>
|
<encoder>
|
||||||
@@ -5,6 +7,9 @@
|
|||||||
</encoder>
|
</encoder>
|
||||||
</appender>
|
</appender>
|
||||||
|
|
||||||
|
<!-- jadx-gui -->
|
||||||
|
<logger name="com.pinterest.ktlint" level="INFO"/>
|
||||||
|
|
||||||
<root level="INFO">
|
<root level="INFO">
|
||||||
<appender-ref ref="STDOUT"/>
|
<appender-ref ref="STDOUT"/>
|
||||||
</root>
|
</root>
|
||||||
|
|||||||
@@ -1,29 +0,0 @@
|
|||||||
plugins {
|
|
||||||
id 'jadx-library'
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
api(project(':jadx-plugins:jadx-plugins-api'))
|
|
||||||
|
|
||||||
implementation 'com.google.code.gson:gson:2.9.0'
|
|
||||||
implementation 'com.android.tools.build:aapt2-proto:4.2.1-7147631'
|
|
||||||
constraints {
|
|
||||||
// Force protobuf version to prevent Java-7 issue
|
|
||||||
implementation 'com.google.protobuf:protobuf-java:3.11.4'
|
|
||||||
}
|
|
||||||
|
|
||||||
testImplementation 'org.apache.commons:commons-lang3:3.12.0'
|
|
||||||
|
|
||||||
testImplementation(project(':jadx-plugins:jadx-dex-input'))
|
|
||||||
testRuntimeOnly(project(':jadx-plugins:jadx-smali-input'))
|
|
||||||
testRuntimeOnly(project(':jadx-plugins:jadx-java-convert'))
|
|
||||||
testRuntimeOnly(project(':jadx-plugins:jadx-java-input'))
|
|
||||||
testRuntimeOnly(project(':jadx-plugins:jadx-raung-input'))
|
|
||||||
|
|
||||||
testImplementation 'org.eclipse.jdt:ecj:3.29.0'
|
|
||||||
testImplementation 'tools.profiler:async-profiler:1.8.3'
|
|
||||||
}
|
|
||||||
|
|
||||||
test {
|
|
||||||
exclude '**/tmp/*'
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
plugins {
|
||||||
|
id("jadx-library")
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
api(project(":jadx-plugins:jadx-input-api"))
|
||||||
|
|
||||||
|
implementation("com.google.code.gson:gson:2.10.1")
|
||||||
|
|
||||||
|
// TODO: move resources decoding to separate plugin module
|
||||||
|
implementation("com.android.tools.build:aapt2-proto:8.2.2-10154469")
|
||||||
|
implementation("com.google.protobuf:protobuf-java:3.25.2") // forcing latest version
|
||||||
|
|
||||||
|
testImplementation("org.apache.commons:commons-lang3:3.14.0")
|
||||||
|
|
||||||
|
testImplementation(project(":jadx-plugins:jadx-dex-input"))
|
||||||
|
testRuntimeOnly(project(":jadx-plugins:jadx-smali-input"))
|
||||||
|
testRuntimeOnly(project(":jadx-plugins:jadx-java-convert"))
|
||||||
|
testRuntimeOnly(project(":jadx-plugins:jadx-java-input"))
|
||||||
|
testRuntimeOnly(project(":jadx-plugins:jadx-raung-input"))
|
||||||
|
|
||||||
|
testImplementation("org.eclipse.jdt:ecj") {
|
||||||
|
version {
|
||||||
|
prefer("3.33.0")
|
||||||
|
strictly("[3.33, 3.34[") // from 3.34 compiled with Java 17
|
||||||
|
}
|
||||||
|
}
|
||||||
|
testImplementation("tools.profiler:async-profiler:3.0")
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.test {
|
||||||
|
exclude("**/tmp/*")
|
||||||
|
}
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
package jadx.api;
|
package jadx.api;
|
||||||
|
|
||||||
|
import java.io.Closeable;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.file.Path;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
@@ -11,17 +12,32 @@ import java.util.Map;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import jadx.api.args.DeobfuscationMapFileMode;
|
import jadx.api.args.GeneratedRenamesMappingFileMode;
|
||||||
|
import jadx.api.args.IntegerFormat;
|
||||||
|
import jadx.api.args.ResourceNameSource;
|
||||||
|
import jadx.api.args.UserRenamesMappingsMode;
|
||||||
import jadx.api.data.ICodeData;
|
import jadx.api.data.ICodeData;
|
||||||
|
import jadx.api.deobf.IAliasProvider;
|
||||||
|
import jadx.api.deobf.IRenameCondition;
|
||||||
import jadx.api.impl.AnnotatedCodeWriter;
|
import jadx.api.impl.AnnotatedCodeWriter;
|
||||||
import jadx.api.impl.InMemoryCodeCache;
|
import jadx.api.impl.InMemoryCodeCache;
|
||||||
|
import jadx.api.plugins.loader.JadxBasePluginLoader;
|
||||||
|
import jadx.api.plugins.loader.JadxPluginLoader;
|
||||||
|
import jadx.api.usage.IUsageInfoCache;
|
||||||
|
import jadx.api.usage.impl.InMemoryUsageInfoCache;
|
||||||
|
import jadx.core.deobf.DeobfAliasProvider;
|
||||||
|
import jadx.core.deobf.conditions.DeobfWhitelist;
|
||||||
|
import jadx.core.deobf.conditions.JadxRenameConditions;
|
||||||
|
import jadx.core.plugins.PluginContext;
|
||||||
import jadx.core.utils.files.FileUtils;
|
import jadx.core.utils.files.FileUtils;
|
||||||
|
|
||||||
public class JadxArgs {
|
public class JadxArgs implements Closeable {
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(JadxArgs.class);
|
private static final Logger LOG = LoggerFactory.getLogger(JadxArgs.class);
|
||||||
|
|
||||||
public static final int DEFAULT_THREADS_COUNT = Math.max(1, Runtime.getRuntime().availableProcessors() / 2);
|
public static final int DEFAULT_THREADS_COUNT = Math.max(1, Runtime.getRuntime().availableProcessors() / 2);
|
||||||
@@ -37,6 +53,13 @@ public class JadxArgs {
|
|||||||
private File outDirRes;
|
private File outDirRes;
|
||||||
|
|
||||||
private ICodeCache codeCache = new InMemoryCodeCache();
|
private ICodeCache codeCache = new InMemoryCodeCache();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Usage data cache. Saves use places of classes, methods and fields between code reloads.
|
||||||
|
* Can be set to {@link jadx.api.usage.impl.EmptyUsageInfoCache} if code reload not needed.
|
||||||
|
*/
|
||||||
|
private IUsageInfoCache usageInfoCache = new InMemoryUsageInfoCache();
|
||||||
|
|
||||||
private Function<JadxArgs, ICodeWriter> codeWriterProvider = AnnotatedCodeWriter::new;
|
private Function<JadxArgs, ICodeWriter> codeWriterProvider = AnnotatedCodeWriter::new;
|
||||||
|
|
||||||
private int threadsCount = DEFAULT_THREADS_COUNT;
|
private int threadsCount = DEFAULT_THREADS_COUNT;
|
||||||
@@ -52,6 +75,8 @@ public class JadxArgs {
|
|||||||
private boolean extractFinally = true;
|
private boolean extractFinally = true;
|
||||||
private boolean inlineAnonymousClasses = true;
|
private boolean inlineAnonymousClasses = true;
|
||||||
private boolean inlineMethods = true;
|
private boolean inlineMethods = true;
|
||||||
|
private boolean allowInlineKotlinLambda = true;
|
||||||
|
private boolean moveInnerClasses = true;
|
||||||
|
|
||||||
private boolean skipResources = false;
|
private boolean skipResources = false;
|
||||||
private boolean skipSources = false;
|
private boolean skipSources = false;
|
||||||
@@ -66,21 +91,41 @@ public class JadxArgs {
|
|||||||
*/
|
*/
|
||||||
private boolean includeDependencies = false;
|
private boolean includeDependencies = false;
|
||||||
|
|
||||||
|
private Path userRenamesMappingsPath = null;
|
||||||
|
private UserRenamesMappingsMode userRenamesMappingsMode = UserRenamesMappingsMode.getDefault();
|
||||||
|
|
||||||
private boolean deobfuscationOn = false;
|
private boolean deobfuscationOn = false;
|
||||||
private boolean useSourceNameAsClassAlias = false;
|
private boolean useSourceNameAsClassAlias = false;
|
||||||
private boolean parseKotlinMetadata = false;
|
|
||||||
private File deobfuscationMapFile = null;
|
|
||||||
|
|
||||||
private DeobfuscationMapFileMode deobfuscationMapFileMode = DeobfuscationMapFileMode.READ;
|
private File generatedRenamesMappingFile = null;
|
||||||
|
private GeneratedRenamesMappingFileMode generatedRenamesMappingFileMode = GeneratedRenamesMappingFileMode.getDefault();
|
||||||
|
private ResourceNameSource resourceNameSource = ResourceNameSource.AUTO;
|
||||||
|
|
||||||
private int deobfuscationMinLength = 0;
|
private int deobfuscationMinLength = 0;
|
||||||
private int deobfuscationMaxLength = Integer.MAX_VALUE;
|
private int deobfuscationMaxLength = Integer.MAX_VALUE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of classes and packages (ends with '.*') to exclude from deobfuscation
|
||||||
|
*/
|
||||||
|
private List<String> deobfuscationWhitelist = DeobfWhitelist.DEFAULT_LIST;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Nodes alias provider for deobfuscator and rename visitor
|
||||||
|
*/
|
||||||
|
private IAliasProvider aliasProvider = new DeobfAliasProvider();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Condition to rename node in deobfuscator
|
||||||
|
*/
|
||||||
|
private IRenameCondition renameCondition = JadxRenameConditions.buildDefault();
|
||||||
|
|
||||||
private boolean escapeUnicode = false;
|
private boolean escapeUnicode = false;
|
||||||
private boolean replaceConsts = true;
|
private boolean replaceConsts = true;
|
||||||
private boolean respectBytecodeAccModifiers = false;
|
private boolean respectBytecodeAccModifiers = false;
|
||||||
private boolean exportAsGradleProject = false;
|
private boolean exportAsGradleProject = false;
|
||||||
|
|
||||||
|
private boolean skipXmlPrettyPrint = false;
|
||||||
|
|
||||||
private boolean fsCaseSensitive;
|
private boolean fsCaseSensitive;
|
||||||
|
|
||||||
public enum RenameEnum {
|
public enum RenameEnum {
|
||||||
@@ -101,6 +146,8 @@ public class JadxArgs {
|
|||||||
|
|
||||||
private CommentsLevel commentsLevel = CommentsLevel.INFO;
|
private CommentsLevel commentsLevel = CommentsLevel.INFO;
|
||||||
|
|
||||||
|
private IntegerFormat integerFormat = IntegerFormat.AUTO;
|
||||||
|
|
||||||
private boolean useDxInput = false;
|
private boolean useDxInput = false;
|
||||||
|
|
||||||
public enum UseKotlinMethodsForVarNames {
|
public enum UseKotlinMethodsForVarNames {
|
||||||
@@ -116,6 +163,10 @@ public class JadxArgs {
|
|||||||
|
|
||||||
private Map<String, String> pluginOptions = new HashMap<>();
|
private Map<String, String> pluginOptions = new HashMap<>();
|
||||||
|
|
||||||
|
private JadxPluginLoader pluginLoader = new JadxBasePluginLoader();
|
||||||
|
|
||||||
|
private boolean loadJadxClsSetFile = true;
|
||||||
|
|
||||||
public JadxArgs() {
|
public JadxArgs() {
|
||||||
// use default options
|
// use default options
|
||||||
}
|
}
|
||||||
@@ -126,16 +177,24 @@ public class JadxArgs {
|
|||||||
setOutDirRes(new File(rootDir, DEFAULT_RES_DIR));
|
setOutDirRes(new File(rootDir, DEFAULT_RES_DIR));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void close() {
|
public void close() {
|
||||||
try {
|
try {
|
||||||
inputFiles = null;
|
inputFiles = null;
|
||||||
if (codeCache != null) {
|
if (codeCache != null) {
|
||||||
codeCache.close();
|
codeCache.close();
|
||||||
}
|
}
|
||||||
|
if (usageInfoCache != null) {
|
||||||
|
usageInfoCache.close();
|
||||||
|
}
|
||||||
|
if (pluginLoader != null) {
|
||||||
|
pluginLoader.close();
|
||||||
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOG.error("Failed to close JadxArgs", e);
|
LOG.error("Failed to close JadxArgs", e);
|
||||||
} finally {
|
} finally {
|
||||||
codeCache = null;
|
codeCache = null;
|
||||||
|
usageInfoCache = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -261,6 +320,22 @@ public class JadxArgs {
|
|||||||
this.inlineMethods = inlineMethods;
|
this.inlineMethods = inlineMethods;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isAllowInlineKotlinLambda() {
|
||||||
|
return allowInlineKotlinLambda;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAllowInlineKotlinLambda(boolean allowInlineKotlinLambda) {
|
||||||
|
this.allowInlineKotlinLambda = allowInlineKotlinLambda;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isMoveInnerClasses() {
|
||||||
|
return moveInnerClasses;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMoveInnerClasses(boolean moveInnerClasses) {
|
||||||
|
this.moveInnerClasses = moveInnerClasses;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isExtractFinally() {
|
public boolean isExtractFinally() {
|
||||||
return extractFinally;
|
return extractFinally;
|
||||||
}
|
}
|
||||||
@@ -301,6 +376,22 @@ public class JadxArgs {
|
|||||||
this.classFilter = classFilter;
|
this.classFilter = classFilter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Path getUserRenamesMappingsPath() {
|
||||||
|
return userRenamesMappingsPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUserRenamesMappingsPath(Path path) {
|
||||||
|
this.userRenamesMappingsPath = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserRenamesMappingsMode getUserRenamesMappingsMode() {
|
||||||
|
return userRenamesMappingsMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUserRenamesMappingsMode(UserRenamesMappingsMode mode) {
|
||||||
|
this.userRenamesMappingsMode = mode;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isDeobfuscationOn() {
|
public boolean isDeobfuscationOn() {
|
||||||
return deobfuscationOn;
|
return deobfuscationOn;
|
||||||
}
|
}
|
||||||
@@ -309,24 +400,22 @@ public class JadxArgs {
|
|||||||
this.deobfuscationOn = deobfuscationOn;
|
this.deobfuscationOn = deobfuscationOn;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
public boolean isDeobfuscationForceSave() {
|
public boolean isDeobfuscationForceSave() {
|
||||||
return deobfuscationMapFileMode == DeobfuscationMapFileMode.OVERWRITE;
|
return generatedRenamesMappingFileMode == GeneratedRenamesMappingFileMode.OVERWRITE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
public void setDeobfuscationForceSave(boolean deobfuscationForceSave) {
|
public void setDeobfuscationForceSave(boolean deobfuscationForceSave) {
|
||||||
if (deobfuscationForceSave) {
|
if (deobfuscationForceSave) {
|
||||||
this.deobfuscationMapFileMode = DeobfuscationMapFileMode.OVERWRITE;
|
this.generatedRenamesMappingFileMode = GeneratedRenamesMappingFileMode.OVERWRITE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public DeobfuscationMapFileMode getDeobfuscationMapFileMode() {
|
public GeneratedRenamesMappingFileMode getGeneratedRenamesMappingFileMode() {
|
||||||
return deobfuscationMapFileMode;
|
return generatedRenamesMappingFileMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDeobfuscationMapFileMode(DeobfuscationMapFileMode deobfuscationMapFileMode) {
|
public void setGeneratedRenamesMappingFileMode(GeneratedRenamesMappingFileMode mode) {
|
||||||
this.deobfuscationMapFileMode = deobfuscationMapFileMode;
|
this.generatedRenamesMappingFileMode = mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isUseSourceNameAsClassAlias() {
|
public boolean isUseSourceNameAsClassAlias() {
|
||||||
@@ -337,14 +426,6 @@ public class JadxArgs {
|
|||||||
this.useSourceNameAsClassAlias = useSourceNameAsClassAlias;
|
this.useSourceNameAsClassAlias = useSourceNameAsClassAlias;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isParseKotlinMetadata() {
|
|
||||||
return parseKotlinMetadata;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setParseKotlinMetadata(boolean parseKotlinMetadata) {
|
|
||||||
this.parseKotlinMetadata = parseKotlinMetadata;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getDeobfuscationMinLength() {
|
public int getDeobfuscationMinLength() {
|
||||||
return deobfuscationMinLength;
|
return deobfuscationMinLength;
|
||||||
}
|
}
|
||||||
@@ -361,12 +442,44 @@ public class JadxArgs {
|
|||||||
this.deobfuscationMaxLength = deobfuscationMaxLength;
|
this.deobfuscationMaxLength = deobfuscationMaxLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
public File getDeobfuscationMapFile() {
|
public List<String> getDeobfuscationWhitelist() {
|
||||||
return deobfuscationMapFile;
|
return this.deobfuscationWhitelist;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDeobfuscationMapFile(File deobfuscationMapFile) {
|
public void setDeobfuscationWhitelist(List<String> deobfuscationWhitelist) {
|
||||||
this.deobfuscationMapFile = deobfuscationMapFile;
|
this.deobfuscationWhitelist = deobfuscationWhitelist;
|
||||||
|
}
|
||||||
|
|
||||||
|
public File getGeneratedRenamesMappingFile() {
|
||||||
|
return generatedRenamesMappingFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGeneratedRenamesMappingFile(File file) {
|
||||||
|
this.generatedRenamesMappingFile = file;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResourceNameSource getResourceNameSource() {
|
||||||
|
return resourceNameSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setResourceNameSource(ResourceNameSource resourceNameSource) {
|
||||||
|
this.resourceNameSource = resourceNameSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IAliasProvider getAliasProvider() {
|
||||||
|
return aliasProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAliasProvider(IAliasProvider aliasProvider) {
|
||||||
|
this.aliasProvider = aliasProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IRenameCondition getRenameCondition() {
|
||||||
|
return renameCondition;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRenameCondition(IRenameCondition renameCondition) {
|
||||||
|
this.renameCondition = renameCondition;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isEscapeUnicode() {
|
public boolean isEscapeUnicode() {
|
||||||
@@ -401,6 +514,14 @@ public class JadxArgs {
|
|||||||
this.exportAsGradleProject = exportAsGradleProject;
|
this.exportAsGradleProject = exportAsGradleProject;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isSkipXmlPrettyPrint() {
|
||||||
|
return skipXmlPrettyPrint;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSkipXmlPrettyPrint(boolean skipXmlPrettyPrint) {
|
||||||
|
this.skipXmlPrettyPrint = skipXmlPrettyPrint;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isFsCaseSensitive() {
|
public boolean isFsCaseSensitive() {
|
||||||
return fsCaseSensitive;
|
return fsCaseSensitive;
|
||||||
}
|
}
|
||||||
@@ -485,6 +606,14 @@ public class JadxArgs {
|
|||||||
this.codeWriterProvider = codeWriterProvider;
|
this.codeWriterProvider = codeWriterProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IUsageInfoCache getUsageInfoCache() {
|
||||||
|
return usageInfoCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUsageInfoCache(IUsageInfoCache usageInfoCache) {
|
||||||
|
this.usageInfoCache = usageInfoCache;
|
||||||
|
}
|
||||||
|
|
||||||
public ICodeData getCodeData() {
|
public ICodeData getCodeData() {
|
||||||
return codeData;
|
return codeData;
|
||||||
}
|
}
|
||||||
@@ -501,6 +630,14 @@ public class JadxArgs {
|
|||||||
this.commentsLevel = commentsLevel;
|
this.commentsLevel = commentsLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IntegerFormat getIntegerFormat() {
|
||||||
|
return integerFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIntegerFormat(IntegerFormat format) {
|
||||||
|
this.integerFormat = format;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isUseDxInput() {
|
public boolean isUseDxInput() {
|
||||||
return useDxInput;
|
return useDxInput;
|
||||||
}
|
}
|
||||||
@@ -533,19 +670,47 @@ public class JadxArgs {
|
|||||||
this.pluginOptions = pluginOptions;
|
this.pluginOptions = pluginOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public JadxPluginLoader getPluginLoader() {
|
||||||
|
return pluginLoader;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPluginLoader(JadxPluginLoader pluginLoader) {
|
||||||
|
this.pluginLoader = pluginLoader;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isLoadJadxClsSetFile() {
|
||||||
|
return loadJadxClsSetFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLoadJadxClsSetFile(boolean loadJadxClsSetFile) {
|
||||||
|
this.loadJadxClsSetFile = loadJadxClsSetFile;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hash of all options that can change result code
|
* Hash of all options that can change result code
|
||||||
*/
|
*/
|
||||||
public String makeCodeArgsHash() {
|
public String makeCodeArgsHash(@Nullable JadxDecompiler decompiler) {
|
||||||
String argStr = "args:" + decompilationMode + useImports + showInconsistentCode
|
String argStr = "args:" + decompilationMode + useImports + showInconsistentCode
|
||||||
+ inlineAnonymousClasses + inlineMethods
|
+ inlineAnonymousClasses + inlineMethods + moveInnerClasses + allowInlineKotlinLambda
|
||||||
+ deobfuscationOn + deobfuscationMinLength + deobfuscationMaxLength
|
+ deobfuscationOn + deobfuscationMinLength + deobfuscationMaxLength + deobfuscationWhitelist
|
||||||
+ parseKotlinMetadata + useKotlinMethodsForVarNames
|
+ resourceNameSource
|
||||||
|
+ useKotlinMethodsForVarNames
|
||||||
+ insertDebugLines + extractFinally
|
+ insertDebugLines + extractFinally
|
||||||
+ debugInfo + useSourceNameAsClassAlias + escapeUnicode + replaceConsts
|
+ debugInfo + useSourceNameAsClassAlias + escapeUnicode + replaceConsts
|
||||||
+ respectBytecodeAccModifiers + fsCaseSensitive + renameFlags
|
+ respectBytecodeAccModifiers + fsCaseSensitive + renameFlags
|
||||||
+ commentsLevel + useDxInput + pluginOptions;
|
+ commentsLevel + useDxInput + integerFormat
|
||||||
return FileUtils.md5Sum(argStr.getBytes(StandardCharsets.US_ASCII));
|
+ "|" + buildPluginsHash(decompiler);
|
||||||
|
return FileUtils.md5Sum(argStr);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String buildPluginsHash(@Nullable JadxDecompiler decompiler) {
|
||||||
|
if (decompiler == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return decompiler.getPluginManager().getResolvedPluginContexts()
|
||||||
|
.stream()
|
||||||
|
.map(PluginContext::getInputsHash)
|
||||||
|
.collect(Collectors.joining(":"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -561,20 +726,24 @@ public class JadxArgs {
|
|||||||
+ ", skipResources=" + skipResources
|
+ ", skipResources=" + skipResources
|
||||||
+ ", skipSources=" + skipSources
|
+ ", skipSources=" + skipSources
|
||||||
+ ", includeDependencies=" + includeDependencies
|
+ ", includeDependencies=" + includeDependencies
|
||||||
|
+ ", userRenamesMappingsPath=" + userRenamesMappingsPath
|
||||||
|
+ ", userRenamesMappingsMode=" + userRenamesMappingsMode
|
||||||
+ ", deobfuscationOn=" + deobfuscationOn
|
+ ", deobfuscationOn=" + deobfuscationOn
|
||||||
+ ", deobfuscationMapFile=" + deobfuscationMapFile
|
+ ", generatedRenamesMappingFile=" + generatedRenamesMappingFile
|
||||||
+ ", deobfuscationMapFileMode=" + deobfuscationMapFileMode
|
+ ", generatedRenamesMappingFileMode=" + generatedRenamesMappingFileMode
|
||||||
|
+ ", resourceNameSource=" + resourceNameSource
|
||||||
+ ", useSourceNameAsClassAlias=" + useSourceNameAsClassAlias
|
+ ", useSourceNameAsClassAlias=" + useSourceNameAsClassAlias
|
||||||
+ ", parseKotlinMetadata=" + parseKotlinMetadata
|
|
||||||
+ ", useKotlinMethodsForVarNames=" + useKotlinMethodsForVarNames
|
+ ", useKotlinMethodsForVarNames=" + useKotlinMethodsForVarNames
|
||||||
+ ", insertDebugLines=" + insertDebugLines
|
+ ", insertDebugLines=" + insertDebugLines
|
||||||
+ ", extractFinally=" + extractFinally
|
+ ", extractFinally=" + extractFinally
|
||||||
+ ", deobfuscationMinLength=" + deobfuscationMinLength
|
+ ", deobfuscationMinLength=" + deobfuscationMinLength
|
||||||
+ ", deobfuscationMaxLength=" + deobfuscationMaxLength
|
+ ", deobfuscationMaxLength=" + deobfuscationMaxLength
|
||||||
|
+ ", deobfuscationWhitelist=" + deobfuscationWhitelist
|
||||||
+ ", escapeUnicode=" + escapeUnicode
|
+ ", escapeUnicode=" + escapeUnicode
|
||||||
+ ", replaceConsts=" + replaceConsts
|
+ ", replaceConsts=" + replaceConsts
|
||||||
+ ", respectBytecodeAccModifiers=" + respectBytecodeAccModifiers
|
+ ", respectBytecodeAccModifiers=" + respectBytecodeAccModifiers
|
||||||
+ ", exportAsGradleProject=" + exportAsGradleProject
|
+ ", exportAsGradleProject=" + exportAsGradleProject
|
||||||
|
+ ", skipXmlPrettyPrint=" + skipXmlPrettyPrint
|
||||||
+ ", fsCaseSensitive=" + fsCaseSensitive
|
+ ", fsCaseSensitive=" + fsCaseSensitive
|
||||||
+ ", renameFlags=" + renameFlags
|
+ ", renameFlags=" + renameFlags
|
||||||
+ ", outputFormat=" + outputFormat
|
+ ", outputFormat=" + outputFormat
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ public class JadxArgsValidator {
|
|||||||
|
|
||||||
private static void checkInputFiles(JadxDecompiler jadx, JadxArgs args) {
|
private static void checkInputFiles(JadxDecompiler jadx, JadxArgs args) {
|
||||||
List<File> inputFiles = args.getInputFiles();
|
List<File> inputFiles = args.getInputFiles();
|
||||||
if (inputFiles.isEmpty() && jadx.getCustomLoads().isEmpty()) {
|
if (inputFiles.isEmpty() && jadx.getCustomCodeLoaders().isEmpty()) {
|
||||||
throw new JadxArgsValidateException("Please specify input file");
|
throw new JadxArgsValidateException("Please specify input file");
|
||||||
}
|
}
|
||||||
for (File inputFile : inputFiles) {
|
for (File inputFile : inputFiles) {
|
||||||
|
|||||||
@@ -6,17 +6,12 @@ import java.nio.file.Path;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
import java.util.concurrent.ThreadPoolExecutor;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@@ -30,28 +25,34 @@ import jadx.api.metadata.ICodeNodeRef;
|
|||||||
import jadx.api.metadata.annotations.NodeDeclareRef;
|
import jadx.api.metadata.annotations.NodeDeclareRef;
|
||||||
import jadx.api.metadata.annotations.VarNode;
|
import jadx.api.metadata.annotations.VarNode;
|
||||||
import jadx.api.metadata.annotations.VarRef;
|
import jadx.api.metadata.annotations.VarRef;
|
||||||
|
import jadx.api.plugins.CustomResourcesLoader;
|
||||||
import jadx.api.plugins.JadxPlugin;
|
import jadx.api.plugins.JadxPlugin;
|
||||||
import jadx.api.plugins.JadxPluginManager;
|
import jadx.api.plugins.events.IJadxEvents;
|
||||||
import jadx.api.plugins.input.JadxInputPlugin;
|
import jadx.api.plugins.input.ICodeLoader;
|
||||||
import jadx.api.plugins.input.data.ILoadResult;
|
import jadx.api.plugins.input.JadxCodeInput;
|
||||||
import jadx.api.plugins.options.JadxPluginOptions;
|
import jadx.api.plugins.pass.JadxPass;
|
||||||
|
import jadx.api.plugins.pass.types.JadxAfterLoadPass;
|
||||||
|
import jadx.api.plugins.pass.types.JadxPassType;
|
||||||
|
import jadx.api.utils.tasks.ITaskExecutor;
|
||||||
import jadx.core.Jadx;
|
import jadx.core.Jadx;
|
||||||
import jadx.core.dex.attributes.AFlag;
|
import jadx.core.dex.attributes.AFlag;
|
||||||
import jadx.core.dex.attributes.AType;
|
|
||||||
import jadx.core.dex.attributes.nodes.InlinedAttr;
|
|
||||||
import jadx.core.dex.nodes.ClassNode;
|
import jadx.core.dex.nodes.ClassNode;
|
||||||
import jadx.core.dex.nodes.FieldNode;
|
import jadx.core.dex.nodes.FieldNode;
|
||||||
import jadx.core.dex.nodes.MethodNode;
|
import jadx.core.dex.nodes.MethodNode;
|
||||||
|
import jadx.core.dex.nodes.PackageNode;
|
||||||
import jadx.core.dex.nodes.RootNode;
|
import jadx.core.dex.nodes.RootNode;
|
||||||
import jadx.core.dex.visitors.SaveCode;
|
import jadx.core.dex.visitors.SaveCode;
|
||||||
import jadx.core.export.ExportGradleProject;
|
import jadx.core.export.ExportGradleTask;
|
||||||
|
import jadx.core.plugins.JadxPluginManager;
|
||||||
|
import jadx.core.plugins.PluginContext;
|
||||||
|
import jadx.core.plugins.events.JadxEventsImpl;
|
||||||
import jadx.core.utils.DecompilerScheduler;
|
import jadx.core.utils.DecompilerScheduler;
|
||||||
import jadx.core.utils.Utils;
|
import jadx.core.utils.Utils;
|
||||||
import jadx.core.utils.exceptions.JadxRuntimeException;
|
import jadx.core.utils.exceptions.JadxRuntimeException;
|
||||||
import jadx.core.utils.files.FileUtils;
|
import jadx.core.utils.files.FileUtils;
|
||||||
|
import jadx.core.utils.tasks.TaskExecutor;
|
||||||
import jadx.core.xmlgen.BinaryXMLParser;
|
import jadx.core.xmlgen.BinaryXMLParser;
|
||||||
import jadx.core.xmlgen.ProtoXMLParser;
|
import jadx.core.xmlgen.ProtoXMLParser;
|
||||||
import jadx.core.xmlgen.ResContainer;
|
|
||||||
import jadx.core.xmlgen.ResourcesSaver;
|
import jadx.core.xmlgen.ResourcesSaver;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -85,8 +86,8 @@ public final class JadxDecompiler implements Closeable {
|
|||||||
private static final Logger LOG = LoggerFactory.getLogger(JadxDecompiler.class);
|
private static final Logger LOG = LoggerFactory.getLogger(JadxDecompiler.class);
|
||||||
|
|
||||||
private final JadxArgs args;
|
private final JadxArgs args;
|
||||||
private final JadxPluginManager pluginManager = new JadxPluginManager();
|
private final JadxPluginManager pluginManager = new JadxPluginManager(this);
|
||||||
private final List<ILoadResult> loadedInputs = new ArrayList<>();
|
private final List<ICodeLoader> loadedInputs = new ArrayList<>();
|
||||||
|
|
||||||
private RootNode root;
|
private RootNode root;
|
||||||
private List<JavaClass> classes;
|
private List<JavaClass> classes;
|
||||||
@@ -95,13 +96,12 @@ public final class JadxDecompiler implements Closeable {
|
|||||||
private BinaryXMLParser binaryXmlParser;
|
private BinaryXMLParser binaryXmlParser;
|
||||||
private ProtoXMLParser protoXmlParser;
|
private ProtoXMLParser protoXmlParser;
|
||||||
|
|
||||||
private final Map<ClassNode, JavaClass> classesMap = new ConcurrentHashMap<>();
|
|
||||||
private final Map<MethodNode, JavaMethod> methodsMap = new ConcurrentHashMap<>();
|
|
||||||
private final Map<FieldNode, JavaField> fieldsMap = new ConcurrentHashMap<>();
|
|
||||||
|
|
||||||
private final IDecompileScheduler decompileScheduler = new DecompilerScheduler();
|
private final IDecompileScheduler decompileScheduler = new DecompilerScheduler();
|
||||||
|
private final JadxEventsImpl events = new JadxEventsImpl();
|
||||||
|
|
||||||
private final List<ILoadResult> customLoads = new ArrayList<>();
|
private final List<ICodeLoader> customCodeLoaders = new ArrayList<>();
|
||||||
|
private final List<CustomResourcesLoader> customResourcesLoaders = new ArrayList<>();
|
||||||
|
private final Map<JadxPassType, List<JadxPass>> customPasses = new HashMap<>();
|
||||||
|
|
||||||
public JadxDecompiler() {
|
public JadxDecompiler() {
|
||||||
this(new JadxArgs());
|
this(new JadxArgs());
|
||||||
@@ -115,15 +115,31 @@ public final class JadxDecompiler implements Closeable {
|
|||||||
reset();
|
reset();
|
||||||
JadxArgsValidator.validate(this);
|
JadxArgsValidator.validate(this);
|
||||||
LOG.info("loading ...");
|
LOG.info("loading ...");
|
||||||
loadPlugins(args);
|
loadPlugins();
|
||||||
loadInputFiles();
|
loadInputFiles();
|
||||||
|
|
||||||
root = new RootNode(args);
|
root = new RootNode(args);
|
||||||
|
root.init();
|
||||||
|
root.setDecompilerRef(this);
|
||||||
|
root.mergePasses(customPasses);
|
||||||
root.loadClasses(loadedInputs);
|
root.loadClasses(loadedInputs);
|
||||||
root.initClassPath();
|
root.initClassPath();
|
||||||
root.loadResources(getResources());
|
root.loadResources(getResources());
|
||||||
root.runPreDecompileStage();
|
root.runPreDecompileStage();
|
||||||
root.initPasses();
|
root.initPasses();
|
||||||
|
loadFinished();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reloadPasses() {
|
||||||
|
LOG.info("reloading (passes only) ...");
|
||||||
|
customPasses.clear();
|
||||||
|
root.resetPasses();
|
||||||
|
events.reset();
|
||||||
|
loadPlugins();
|
||||||
|
root.mergePasses(customPasses);
|
||||||
|
root.restartVisitors();
|
||||||
|
root.initPasses();
|
||||||
|
loadFinished();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadInputFiles() {
|
private void loadInputFiles() {
|
||||||
@@ -131,42 +147,38 @@ public final class JadxDecompiler implements Closeable {
|
|||||||
List<Path> inputPaths = Utils.collectionMap(args.getInputFiles(), File::toPath);
|
List<Path> inputPaths = Utils.collectionMap(args.getInputFiles(), File::toPath);
|
||||||
List<Path> inputFiles = FileUtils.expandDirs(inputPaths);
|
List<Path> inputFiles = FileUtils.expandDirs(inputPaths);
|
||||||
long start = System.currentTimeMillis();
|
long start = System.currentTimeMillis();
|
||||||
for (JadxInputPlugin inputPlugin : pluginManager.getInputPlugins()) {
|
for (PluginContext plugin : pluginManager.getResolvedPluginContexts()) {
|
||||||
ILoadResult loadResult = inputPlugin.loadFiles(inputFiles);
|
for (JadxCodeInput codeLoader : plugin.getCodeInputs()) {
|
||||||
if (loadResult != null && !loadResult.isEmpty()) {
|
try {
|
||||||
loadedInputs.add(loadResult);
|
ICodeLoader loader = codeLoader.loadFiles(inputFiles);
|
||||||
|
if (loader != null && !loader.isEmpty()) {
|
||||||
|
loadedInputs.add(loader);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new JadxRuntimeException("Failed to load code for plugin: " + plugin, e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
loadedInputs.addAll(customLoads);
|
loadedInputs.addAll(customCodeLoaders);
|
||||||
if (LOG.isDebugEnabled()) {
|
if (LOG.isDebugEnabled()) {
|
||||||
LOG.debug("Loaded using {} inputs plugin in {} ms", loadedInputs.size(), System.currentTimeMillis() - start);
|
LOG.debug("Loaded using {} inputs plugin in {} ms", loadedInputs.size(), System.currentTimeMillis() - start);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addCustomLoad(ILoadResult customLoad) {
|
|
||||||
customLoads.add(customLoad);
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<ILoadResult> getCustomLoads() {
|
|
||||||
return customLoads;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void reset() {
|
private void reset() {
|
||||||
root = null;
|
root = null;
|
||||||
classes = null;
|
classes = null;
|
||||||
resources = null;
|
resources = null;
|
||||||
binaryXmlParser = null;
|
binaryXmlParser = null;
|
||||||
protoXmlParser = null;
|
protoXmlParser = null;
|
||||||
|
events.reset();
|
||||||
classesMap.clear();
|
|
||||||
methodsMap.clear();
|
|
||||||
fieldsMap.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() {
|
public void close() {
|
||||||
reset();
|
reset();
|
||||||
closeInputs();
|
closeInputs();
|
||||||
|
closeLoaders();
|
||||||
args.close();
|
args.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,23 +193,37 @@ public final class JadxDecompiler implements Closeable {
|
|||||||
loadedInputs.clear();
|
loadedInputs.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadPlugins(JadxArgs args) {
|
private void closeLoaders() {
|
||||||
pluginManager.providesSuggestion("java-input", args.isUseDxInput() ? "java-convert" : "java-input");
|
for (CustomResourcesLoader resourcesLoader : customResourcesLoaders) {
|
||||||
pluginManager.load();
|
try {
|
||||||
if (LOG.isDebugEnabled()) {
|
resourcesLoader.close();
|
||||||
LOG.debug("Resolved plugins: {}", Utils.collectionMap(pluginManager.getResolvedPlugins(),
|
} catch (Exception e) {
|
||||||
p -> p.getPluginInfo().getPluginId()));
|
LOG.error("Failed to close resource loader: " + resourcesLoader, e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Map<String, String> pluginOptions = args.getPluginOptions();
|
customResourcesLoaders.clear();
|
||||||
if (!pluginOptions.isEmpty()) {
|
}
|
||||||
LOG.debug("Applying plugin options: {}", pluginOptions);
|
|
||||||
for (JadxPluginOptions plugin : pluginManager.getPluginsWithOptions()) {
|
private void loadPlugins() {
|
||||||
try {
|
pluginManager.providesSuggestion("java-input", args.isUseDxInput() ? "java-convert" : "java-input");
|
||||||
plugin.setOptions(pluginOptions);
|
pluginManager.load(args.getPluginLoader());
|
||||||
} catch (Exception e) {
|
if (LOG.isDebugEnabled()) {
|
||||||
String pluginId = plugin.getPluginInfo().getPluginId();
|
LOG.debug("Resolved plugins: {}", pluginManager.getResolvedPluginContexts());
|
||||||
throw new JadxRuntimeException("Failed to apply options for plugin: " + pluginId, e);
|
}
|
||||||
}
|
pluginManager.initResolved();
|
||||||
|
if (LOG.isDebugEnabled()) {
|
||||||
|
List<String> passes = customPasses.values().stream().flatMap(Collection::stream)
|
||||||
|
.map(p -> p.getInfo().getName()).collect(Collectors.toList());
|
||||||
|
LOG.debug("Loaded custom passes: {} {}", passes.size(), passes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadFinished() {
|
||||||
|
LOG.debug("Load finished");
|
||||||
|
List<JadxPass> list = customPasses.get(JadxAfterLoadPass.TYPE);
|
||||||
|
if (list != null) {
|
||||||
|
for (JadxPass pass : list) {
|
||||||
|
((JadxAfterLoadPass) pass).init(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -221,13 +247,12 @@ public final class JadxDecompiler implements Closeable {
|
|||||||
|
|
||||||
@SuppressWarnings("BusyWait")
|
@SuppressWarnings("BusyWait")
|
||||||
public void save(int intervalInMillis, ProgressListener listener) {
|
public void save(int intervalInMillis, ProgressListener listener) {
|
||||||
ThreadPoolExecutor ex = (ThreadPoolExecutor) getSaveExecutor();
|
|
||||||
ex.shutdown();
|
|
||||||
try {
|
try {
|
||||||
long total = ex.getTaskCount();
|
ITaskExecutor tasks = getSaveTaskExecutor();
|
||||||
while (ex.isTerminating()) {
|
tasks.execute();
|
||||||
long done = ex.getCompletedTaskCount();
|
long total = tasks.getTasksCount();
|
||||||
listener.progress(done, total);
|
while (tasks.isRunning()) {
|
||||||
|
listener.progress(tasks.getProgress(), total);
|
||||||
Thread.sleep(intervalInMillis);
|
Thread.sleep(intervalInMillis);
|
||||||
}
|
}
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
@@ -244,97 +269,122 @@ public final class JadxDecompiler implements Closeable {
|
|||||||
save(false, true);
|
save(false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("ResultOfMethodCallIgnored")
|
|
||||||
private void save(boolean saveSources, boolean saveResources) {
|
private void save(boolean saveSources, boolean saveResources) {
|
||||||
ExecutorService ex = getSaveExecutor(saveSources, saveResources);
|
ITaskExecutor executor = getSaveTasks(saveSources, saveResources);
|
||||||
ex.shutdown();
|
executor.execute();
|
||||||
try {
|
executor.awaitTermination();
|
||||||
ex.awaitTermination(1, TimeUnit.DAYS);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
LOG.error("Save interrupted", e);
|
|
||||||
Thread.currentThread().interrupt();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ExecutorService getSaveExecutor() {
|
public ITaskExecutor getSaveTaskExecutor() {
|
||||||
return getSaveExecutor(!args.isSkipSources(), !args.isSkipResources());
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Runnable> getSaveTasks() {
|
|
||||||
return getSaveTasks(!args.isSkipSources(), !args.isSkipResources());
|
return getSaveTasks(!args.isSkipSources(), !args.isSkipResources());
|
||||||
}
|
}
|
||||||
|
|
||||||
private ExecutorService getSaveExecutor(boolean saveSources, boolean saveResources) {
|
@Deprecated(forRemoval = true)
|
||||||
int threadsCount = args.getThreadsCount();
|
public ExecutorService getSaveExecutor() {
|
||||||
LOG.debug("processing threads count: {}", threadsCount);
|
ITaskExecutor executor = getSaveTaskExecutor();
|
||||||
LOG.info("processing ...");
|
executor.execute();
|
||||||
ExecutorService executor = Executors.newFixedThreadPool(threadsCount);
|
return executor.getInternalExecutor();
|
||||||
List<Runnable> tasks = getSaveTasks(saveSources, saveResources);
|
|
||||||
tasks.forEach(executor::execute);
|
|
||||||
return executor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Runnable> getSaveTasks(boolean saveSources, boolean saveResources) {
|
@Deprecated(forRemoval = true)
|
||||||
|
public List<Runnable> getSaveTasks() {
|
||||||
|
return Collections.singletonList(this::save);
|
||||||
|
}
|
||||||
|
|
||||||
|
private TaskExecutor getSaveTasks(boolean saveSources, boolean saveResources) {
|
||||||
if (root == null) {
|
if (root == null) {
|
||||||
throw new JadxRuntimeException("No loaded files");
|
throw new JadxRuntimeException("No loaded files");
|
||||||
}
|
}
|
||||||
File sourcesOutDir;
|
File sourcesOutDir;
|
||||||
File resOutDir;
|
File resOutDir;
|
||||||
|
ExportGradleTask gradleExportTask;
|
||||||
if (args.isExportAsGradleProject()) {
|
if (args.isExportAsGradleProject()) {
|
||||||
ResourceFile androidManifest = resources.stream()
|
gradleExportTask = new ExportGradleTask(resources, root, args.getOutDir());
|
||||||
.filter(resourceFile -> resourceFile.getType() == ResourceType.MANIFEST)
|
gradleExportTask.init();
|
||||||
.findFirst()
|
sourcesOutDir = gradleExportTask.getSrcOutDir();
|
||||||
.orElseThrow(IllegalStateException::new);
|
resOutDir = gradleExportTask.getResOutDir();
|
||||||
|
|
||||||
ResContainer strings = resources.stream()
|
|
||||||
.filter(resourceFile -> resourceFile.getType() == ResourceType.ARSC)
|
|
||||||
.findFirst()
|
|
||||||
.orElseThrow(IllegalStateException::new)
|
|
||||||
.loadContent()
|
|
||||||
.getSubFiles()
|
|
||||||
.stream()
|
|
||||||
.filter(resContainer -> resContainer.getFileName().contains("strings.xml"))
|
|
||||||
.findFirst()
|
|
||||||
.orElseThrow(IllegalStateException::new);
|
|
||||||
|
|
||||||
ExportGradleProject export = new ExportGradleProject(root, args.getOutDir(), androidManifest, strings);
|
|
||||||
export.init();
|
|
||||||
sourcesOutDir = export.getSrcOutDir();
|
|
||||||
resOutDir = export.getResOutDir();
|
|
||||||
} else {
|
} else {
|
||||||
sourcesOutDir = args.getOutDirSrc();
|
sourcesOutDir = args.getOutDirSrc();
|
||||||
resOutDir = args.getOutDirRes();
|
resOutDir = args.getOutDirRes();
|
||||||
|
gradleExportTask = null;
|
||||||
}
|
}
|
||||||
List<Runnable> tasks = new ArrayList<>();
|
|
||||||
// save resources first because decompilation can hang or fail
|
TaskExecutor executor = new TaskExecutor();
|
||||||
|
executor.setThreadsCount(args.getThreadsCount());
|
||||||
if (saveResources) {
|
if (saveResources) {
|
||||||
appendResourcesSaveTasks(tasks, resOutDir);
|
// save resources first because decompilation can stop or fail
|
||||||
|
appendResourcesSaveTasks(executor, resOutDir);
|
||||||
}
|
}
|
||||||
if (saveSources) {
|
if (saveSources) {
|
||||||
appendSourcesSave(tasks, sourcesOutDir);
|
appendSourcesSave(executor, sourcesOutDir);
|
||||||
}
|
}
|
||||||
return tasks;
|
if (gradleExportTask != null) {
|
||||||
|
executor.addSequentialTask(gradleExportTask);
|
||||||
|
}
|
||||||
|
return executor;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void appendResourcesSaveTasks(List<Runnable> tasks, File outDir) {
|
private void appendResourcesSaveTasks(ITaskExecutor executor, File outDir) {
|
||||||
if (args.isSkipFilesSave()) {
|
if (args.isSkipFilesSave()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Set<String> inputFileNames = args.getInputFiles().stream().map(File::getAbsolutePath).collect(Collectors.toSet());
|
// process AndroidManifest.xml first to load complete resource ids table
|
||||||
for (ResourceFile resourceFile : getResources()) {
|
for (ResourceFile resourceFile : getResources()) {
|
||||||
if (resourceFile.getType() != ResourceType.ARSC
|
if (resourceFile.getType() == ResourceType.MANIFEST) {
|
||||||
|
new ResourcesSaver(outDir, resourceFile).run();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Set<String> inputFileNames = args.getInputFiles().stream()
|
||||||
|
.map(File::getAbsolutePath)
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
List<Runnable> tasks = new ArrayList<>();
|
||||||
|
for (ResourceFile resourceFile : getResources()) {
|
||||||
|
ResourceType resType = resourceFile.getType();
|
||||||
|
if (resType == ResourceType.MANIFEST) {
|
||||||
|
// already processed
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (resType != ResourceType.ARSC
|
||||||
&& inputFileNames.contains(resourceFile.getOriginalName())) {
|
&& inputFileNames.contains(resourceFile.getOriginalName())) {
|
||||||
// ignore resource made from input file
|
// ignore resource made from input file
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
tasks.add(new ResourcesSaver(outDir, resourceFile));
|
tasks.add(new ResourcesSaver(outDir, resourceFile));
|
||||||
}
|
}
|
||||||
|
executor.addParallelTasks(tasks);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void appendSourcesSave(List<Runnable> tasks, File outDir) {
|
private void appendSourcesSave(ITaskExecutor executor, File outDir) {
|
||||||
Predicate<String> classFilter = args.getClassFilter();
|
|
||||||
List<JavaClass> classes = getClasses();
|
List<JavaClass> classes = getClasses();
|
||||||
List<JavaClass> processQueue = new ArrayList<>(classes.size());
|
List<JavaClass> processQueue = filterClasses(classes);
|
||||||
|
List<List<JavaClass>> batches;
|
||||||
|
try {
|
||||||
|
batches = decompileScheduler.buildBatches(processQueue);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new JadxRuntimeException("Decompilation batches build failed", e);
|
||||||
|
}
|
||||||
|
List<Runnable> decompileTasks = new ArrayList<>(batches.size());
|
||||||
|
for (List<JavaClass> decompileBatch : batches) {
|
||||||
|
decompileTasks.add(() -> {
|
||||||
|
for (JavaClass cls : decompileBatch) {
|
||||||
|
try {
|
||||||
|
ClassNode clsNode = cls.getClassNode();
|
||||||
|
ICodeInfo code = clsNode.getCode();
|
||||||
|
SaveCode.save(outDir, clsNode, code);
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOG.error("Error saving class: {}", cls, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
executor.addParallelTasks(decompileTasks);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<JavaClass> filterClasses(List<JavaClass> classes) {
|
||||||
|
Predicate<String> classFilter = args.getClassFilter();
|
||||||
|
List<JavaClass> list = new ArrayList<>(classes.size());
|
||||||
for (JavaClass cls : classes) {
|
for (JavaClass cls : classes) {
|
||||||
ClassNode clsNode = cls.getClassNode();
|
ClassNode clsNode = cls.getClassNode();
|
||||||
if (clsNode.contains(AFlag.DONT_GENERATE)) {
|
if (clsNode.contains(AFlag.DONT_GENERATE)) {
|
||||||
@@ -346,26 +396,9 @@ public final class JadxDecompiler implements Closeable {
|
|||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
processQueue.add(cls);
|
list.add(cls);
|
||||||
}
|
|
||||||
List<List<JavaClass>> batches;
|
|
||||||
try {
|
|
||||||
batches = decompileScheduler.buildBatches(processQueue);
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new JadxRuntimeException("Decompilation batches build failed", e);
|
|
||||||
}
|
|
||||||
for (List<JavaClass> decompileBatch : batches) {
|
|
||||||
tasks.add(() -> {
|
|
||||||
for (JavaClass cls : decompileBatch) {
|
|
||||||
try {
|
|
||||||
ICodeInfo code = cls.getCodeInfo();
|
|
||||||
SaveCode.save(outDir, cls.getClassNode(), code);
|
|
||||||
} catch (Exception e) {
|
|
||||||
LOG.error("Error saving class: {}", cls, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<JavaClass> getClasses() {
|
public List<JavaClass> getClasses() {
|
||||||
@@ -392,7 +425,7 @@ public final class JadxDecompiler implements Closeable {
|
|||||||
return Utils.collectionMap(root.getClasses(), this::convertClassNode);
|
return Utils.collectionMap(root.getClasses(), this::convertClassNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<ResourceFile> getResources() {
|
public synchronized List<ResourceFile> getResources() {
|
||||||
if (resources == null) {
|
if (resources == null) {
|
||||||
if (root == null) {
|
if (root == null) {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
@@ -403,25 +436,7 @@ public final class JadxDecompiler implements Closeable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public List<JavaPackage> getPackages() {
|
public List<JavaPackage> getPackages() {
|
||||||
List<JavaClass> classList = getClasses();
|
return Utils.collectionMap(root.getPackages(), this::convertPackageNode);
|
||||||
if (classList.isEmpty()) {
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
Map<String, List<JavaClass>> map = new HashMap<>();
|
|
||||||
for (JavaClass javaClass : classList) {
|
|
||||||
String pkg = javaClass.getPackage();
|
|
||||||
List<JavaClass> clsList = map.computeIfAbsent(pkg, k -> new ArrayList<>());
|
|
||||||
clsList.add(javaClass);
|
|
||||||
}
|
|
||||||
List<JavaPackage> packages = new ArrayList<>(map.size());
|
|
||||||
for (Map.Entry<String, List<JavaClass>> entry : map.entrySet()) {
|
|
||||||
packages.add(new JavaPackage(entry.getKey(), entry.getValue()));
|
|
||||||
}
|
|
||||||
Collections.sort(packages);
|
|
||||||
for (JavaPackage pkg : packages) {
|
|
||||||
pkg.getClasses().sort(Comparator.comparing(JavaClass::getName, String.CASE_INSENSITIVE_ORDER));
|
|
||||||
}
|
|
||||||
return Collections.unmodifiableList(packages);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getErrorsCount() {
|
public int getErrorsCount() {
|
||||||
@@ -472,47 +487,56 @@ public final class JadxDecompiler implements Closeable {
|
|||||||
* Get JavaClass by ClassNode without loading and decompilation
|
* Get JavaClass by ClassNode without loading and decompilation
|
||||||
*/
|
*/
|
||||||
@ApiStatus.Internal
|
@ApiStatus.Internal
|
||||||
JavaClass convertClassNode(ClassNode cls) {
|
synchronized JavaClass convertClassNode(ClassNode cls) {
|
||||||
return classesMap.compute(cls, (node, prevJavaCls) -> {
|
JavaClass javaClass = cls.getJavaNode();
|
||||||
if (prevJavaCls != null && prevJavaCls.getClassNode() == cls) {
|
if (javaClass == null) {
|
||||||
// keep previous variable
|
javaClass = cls.isInner()
|
||||||
return prevJavaCls;
|
? new JavaClass(cls, convertClassNode(cls.getParentClass()))
|
||||||
}
|
: new JavaClass(cls, this);
|
||||||
if (cls.isInner()) {
|
cls.setJavaNode(javaClass);
|
||||||
return new JavaClass(cls, convertClassNode(cls.getParentClass()));
|
}
|
||||||
}
|
return javaClass;
|
||||||
return new JavaClass(cls, this);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ApiStatus.Internal
|
@ApiStatus.Internal
|
||||||
JavaField convertFieldNode(FieldNode field) {
|
synchronized JavaField convertFieldNode(FieldNode fld) {
|
||||||
return fieldsMap.computeIfAbsent(field, fldNode -> {
|
JavaField javaField = fld.getJavaNode();
|
||||||
JavaClass parentCls = convertClassNode(fldNode.getParentClass());
|
if (javaField == null) {
|
||||||
return new JavaField(parentCls, fldNode);
|
JavaClass parentCls = convertClassNode(fld.getParentClass());
|
||||||
});
|
javaField = new JavaField(parentCls, fld);
|
||||||
|
fld.setJavaNode(javaField);
|
||||||
|
}
|
||||||
|
return javaField;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ApiStatus.Internal
|
@ApiStatus.Internal
|
||||||
JavaMethod convertMethodNode(MethodNode method) {
|
synchronized JavaMethod convertMethodNode(MethodNode mth) {
|
||||||
return methodsMap.computeIfAbsent(method, mthNode -> {
|
JavaMethod javaMethod = mth.getJavaNode();
|
||||||
ClassNode codeCls = getCodeParentClass(mthNode.getParentClass());
|
if (javaMethod == null) {
|
||||||
return new JavaMethod(convertClassNode(codeCls), mthNode);
|
javaMethod = new JavaMethod(convertClassNode(mth.getParentClass()), mth);
|
||||||
});
|
mth.setJavaNode(javaMethod);
|
||||||
|
}
|
||||||
|
return javaMethod;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ClassNode getCodeParentClass(ClassNode cls) {
|
@ApiStatus.Internal
|
||||||
ClassNode codeCls;
|
synchronized JavaPackage convertPackageNode(PackageNode pkg) {
|
||||||
InlinedAttr inlinedAttr = cls.get(AType.INLINED);
|
JavaPackage foundPkg = pkg.getJavaNode();
|
||||||
if (inlinedAttr != null) {
|
if (foundPkg != null) {
|
||||||
codeCls = inlinedAttr.getInlineCls().getTopParentClass();
|
return foundPkg;
|
||||||
} else {
|
|
||||||
codeCls = cls.getTopParentClass();
|
|
||||||
}
|
}
|
||||||
if (codeCls == cls) {
|
List<JavaClass> clsList = Utils.collectionMap(pkg.getClasses(), this::convertClassNode);
|
||||||
return codeCls;
|
int subPkgsCount = pkg.getSubPackages().size();
|
||||||
|
List<JavaPackage> subPkgs = subPkgsCount == 0 ? Collections.emptyList() : new ArrayList<>(subPkgsCount);
|
||||||
|
JavaPackage javaPkg = new JavaPackage(pkg, clsList, subPkgs);
|
||||||
|
if (subPkgsCount != 0) {
|
||||||
|
// add subpackages after parent to avoid endless recursion
|
||||||
|
for (PackageNode subPackage : pkg.getSubPackages()) {
|
||||||
|
subPkgs.add(convertPackageNode(subPackage));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return getCodeParentClass(codeCls);
|
pkg.setJavaNode(javaPkg);
|
||||||
|
return javaPkg;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@@ -589,14 +613,9 @@ public final class JadxDecompiler implements Closeable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
|
||||||
private JavaVariable resolveVarNode(VarNode varNode) {
|
private JavaVariable resolveVarNode(VarNode varNode) {
|
||||||
MethodNode mthNode = varNode.getMth();
|
JavaMethod javaNode = convertMethodNode(varNode.getMth());
|
||||||
JavaMethod mth = convertMethodNode(mthNode);
|
return new JavaVariable(javaNode, varNode);
|
||||||
if (mth == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return new JavaVariable(mth, varNode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@@ -658,6 +677,33 @@ public final class JadxDecompiler implements Closeable {
|
|||||||
return decompileScheduler;
|
return decompileScheduler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IJadxEvents events() {
|
||||||
|
return events;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addCustomCodeLoader(ICodeLoader customCodeLoader) {
|
||||||
|
customCodeLoaders.add(customCodeLoader);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ICodeLoader> getCustomCodeLoaders() {
|
||||||
|
return customCodeLoaders;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addCustomResourcesLoader(CustomResourcesLoader loader) {
|
||||||
|
if (customResourcesLoaders.contains(loader)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
customResourcesLoaders.add(loader);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<CustomResourcesLoader> getCustomResourcesLoaders() {
|
||||||
|
return customResourcesLoaders;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addCustomPass(JadxPass pass) {
|
||||||
|
customPasses.computeIfAbsent(pass.getPassType(), l -> new ArrayList<>()).add(pass);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "jadx decompiler " + getVersion();
|
return "jadx decompiler " + getVersion();
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import jadx.api.metadata.ICodeNodeRef;
|
|||||||
import jadx.core.dex.attributes.AFlag;
|
import jadx.core.dex.attributes.AFlag;
|
||||||
import jadx.core.dex.attributes.AType;
|
import jadx.core.dex.attributes.AType;
|
||||||
import jadx.core.dex.attributes.nodes.AnonymousClassAttr;
|
import jadx.core.dex.attributes.nodes.AnonymousClassAttr;
|
||||||
|
import jadx.core.dex.attributes.nodes.InlinedAttr;
|
||||||
import jadx.core.dex.info.AccessInfo;
|
import jadx.core.dex.info.AccessInfo;
|
||||||
import jadx.core.dex.nodes.ClassNode;
|
import jadx.core.dex.nodes.ClassNode;
|
||||||
import jadx.core.dex.nodes.FieldNode;
|
import jadx.core.dex.nodes.FieldNode;
|
||||||
@@ -57,7 +58,10 @@ public final class JavaClass implements JavaNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull ICodeInfo getCodeInfo() {
|
public @NotNull ICodeInfo getCodeInfo() {
|
||||||
load();
|
ICodeInfo code = load();
|
||||||
|
if (code != null) {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
return cls.decompile();
|
return cls.decompile();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,6 +99,11 @@ public final class JavaClass implements JavaNode {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ICodeNodeRef getCodeNodeRef() {
|
||||||
|
return cls;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal API. Not Stable!
|
* Internal API. Not Stable!
|
||||||
*/
|
*/
|
||||||
@@ -106,19 +115,24 @@ public final class JavaClass implements JavaNode {
|
|||||||
/**
|
/**
|
||||||
* Decompile class and loads internal lists of fields, methods, etc.
|
* Decompile class and loads internal lists of fields, methods, etc.
|
||||||
* Do nothing if already loaded.
|
* Do nothing if already loaded.
|
||||||
|
*
|
||||||
|
* @return code info if decompilation was executed, null otherwise
|
||||||
*/
|
*/
|
||||||
@Nullable
|
private synchronized @Nullable ICodeInfo load() {
|
||||||
private synchronized void load() {
|
|
||||||
if (listsLoaded) {
|
if (listsLoaded) {
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
listsLoaded = true;
|
listsLoaded = true;
|
||||||
JadxDecompiler rootDecompiler = getRootDecompiler();
|
|
||||||
ICodeCache codeCache = rootDecompiler.getArgs().getCodeCache();
|
ICodeInfo code;
|
||||||
if (!codeCache.contains(cls.getRawName())) {
|
if (cls.getState().isProcessComplete()) {
|
||||||
cls.decompile();
|
// already decompiled -> class internals loaded
|
||||||
|
code = null;
|
||||||
|
} else {
|
||||||
|
code = cls.decompile();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JadxDecompiler rootDecompiler = getRootDecompiler();
|
||||||
int inClsCount = cls.getInnerClasses().size();
|
int inClsCount = cls.getInnerClasses().size();
|
||||||
if (inClsCount != 0) {
|
if (inClsCount != 0) {
|
||||||
List<JavaClass> list = new ArrayList<>(inClsCount);
|
List<JavaClass> list = new ArrayList<>(inClsCount);
|
||||||
@@ -164,6 +178,7 @@ public final class JavaClass implements JavaNode {
|
|||||||
mths.sort(Comparator.comparing(JavaMethod::getName));
|
mths.sort(Comparator.comparing(JavaMethod::getName));
|
||||||
this.methods = Collections.unmodifiableList(mths);
|
this.methods = Collections.unmodifiableList(mths);
|
||||||
}
|
}
|
||||||
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
JadxDecompiler getRootDecompiler() {
|
JadxDecompiler getRootDecompiler() {
|
||||||
@@ -242,19 +257,37 @@ public final class JavaClass implements JavaNode {
|
|||||||
return parent;
|
return parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public JavaClass getOriginalTopParentClass() {
|
||||||
public JavaClass getTopParentClass() {
|
return parent == null ? this : parent.getOriginalTopParentClass();
|
||||||
if (cls.contains(AType.ANONYMOUS_CLASS)) {
|
|
||||||
// moved to usage class
|
|
||||||
return getParentForAnonymousClass();
|
|
||||||
}
|
|
||||||
return parent == null ? this : parent.getTopParentClass();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private JavaClass getParentForAnonymousClass() {
|
/**
|
||||||
AnonymousClassAttr attr = cls.get(AType.ANONYMOUS_CLASS);
|
* Return top parent class which contains code of this class.
|
||||||
ClassNode topParentClass = attr.getOuterCls().getTopParentClass();
|
* Code parent can be different from original parent after move or inline
|
||||||
return getRootDecompiler().convertClassNode(topParentClass);
|
*
|
||||||
|
* @return this if already a top class
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public JavaClass getTopParentClass() {
|
||||||
|
JavaClass codeParent = getCodeParent();
|
||||||
|
return codeParent == null ? this : codeParent.getTopParentClass();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return parent class which contains code of this class.
|
||||||
|
* Code parent can be different for original parent after move or inline
|
||||||
|
*/
|
||||||
|
public @Nullable JavaClass getCodeParent() {
|
||||||
|
AnonymousClassAttr anonymousClsAttr = cls.get(AType.ANONYMOUS_CLASS);
|
||||||
|
if (anonymousClsAttr != null) {
|
||||||
|
// moved to usage class
|
||||||
|
return getRootDecompiler().convertClassNode(anonymousClsAttr.getOuterCls());
|
||||||
|
}
|
||||||
|
InlinedAttr inlinedAttr = cls.get(AType.INLINED);
|
||||||
|
if (inlinedAttr != null) {
|
||||||
|
return getRootDecompiler().convertClassNode(inlinedAttr.getInlineCls());
|
||||||
|
}
|
||||||
|
return parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AccessInfo getAccessInfo() {
|
public AccessInfo getAccessInfo() {
|
||||||
@@ -301,7 +334,7 @@ public final class JavaClass implements JavaNode {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeAlias() {
|
public void removeAlias() {
|
||||||
this.cls.getClassInfo().removeAlias();
|
cls.removeAlias();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import java.util.List;
|
|||||||
import org.jetbrains.annotations.ApiStatus;
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
|
|
||||||
import jadx.api.metadata.ICodeAnnotation;
|
import jadx.api.metadata.ICodeAnnotation;
|
||||||
|
import jadx.api.metadata.ICodeNodeRef;
|
||||||
import jadx.core.dex.info.AccessInfo;
|
import jadx.core.dex.info.AccessInfo;
|
||||||
import jadx.core.dex.instructions.args.ArgType;
|
import jadx.core.dex.instructions.args.ArgType;
|
||||||
import jadx.core.dex.nodes.FieldNode;
|
import jadx.core.dex.nodes.FieldNode;
|
||||||
@@ -74,6 +75,11 @@ public final class JavaField implements JavaNode {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ICodeNodeRef getCodeNodeRef() {
|
||||||
|
return field;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal API. Not Stable!
|
* Internal API. Not Stable!
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import org.slf4j.Logger;
|
|||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import jadx.api.metadata.ICodeAnnotation;
|
import jadx.api.metadata.ICodeAnnotation;
|
||||||
|
import jadx.api.metadata.ICodeNodeRef;
|
||||||
import jadx.core.dex.attributes.AType;
|
import jadx.core.dex.attributes.AType;
|
||||||
import jadx.core.dex.attributes.nodes.MethodOverrideAttr;
|
import jadx.core.dex.attributes.nodes.MethodOverrideAttr;
|
||||||
import jadx.core.dex.info.AccessInfo;
|
import jadx.core.dex.info.AccessInfo;
|
||||||
@@ -116,6 +117,11 @@ public final class JavaMethod implements JavaNode {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ICodeNodeRef getCodeNodeRef() {
|
||||||
|
return mth;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal API. Not Stable!
|
* Internal API. Not Stable!
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -3,9 +3,12 @@ package jadx.api;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import jadx.api.metadata.ICodeAnnotation;
|
import jadx.api.metadata.ICodeAnnotation;
|
||||||
|
import jadx.api.metadata.ICodeNodeRef;
|
||||||
|
|
||||||
public interface JavaNode {
|
public interface JavaNode {
|
||||||
|
|
||||||
|
ICodeNodeRef getCodeNodeRef();
|
||||||
|
|
||||||
String getName();
|
String getName();
|
||||||
|
|
||||||
String getFullName();
|
String getFullName();
|
||||||
@@ -18,8 +21,7 @@ public interface JavaNode {
|
|||||||
|
|
||||||
List<JavaNode> getUseIn();
|
List<JavaNode> getUseIn();
|
||||||
|
|
||||||
default void removeAlias() {
|
void removeAlias();
|
||||||
}
|
|
||||||
|
|
||||||
boolean isOwnCodeAnnotation(ICodeAnnotation ann);
|
boolean isOwnCodeAnnotation(ICodeAnnotation ann);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,36 +1,91 @@
|
|||||||
package jadx.api;
|
package jadx.api;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.ApiStatus.Internal;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import jadx.api.metadata.ICodeAnnotation;
|
import jadx.api.metadata.ICodeAnnotation;
|
||||||
|
import jadx.api.metadata.ICodeNodeRef;
|
||||||
|
import jadx.core.dex.info.PackageInfo;
|
||||||
|
import jadx.core.dex.nodes.PackageNode;
|
||||||
|
|
||||||
public final class JavaPackage implements JavaNode, Comparable<JavaPackage> {
|
public final class JavaPackage implements JavaNode, Comparable<JavaPackage> {
|
||||||
private final String name;
|
private final PackageNode pkgNode;
|
||||||
private final List<JavaClass> classes;
|
private final List<JavaClass> classes;
|
||||||
|
private final List<JavaPackage> subPkgs;
|
||||||
|
|
||||||
JavaPackage(String name, List<JavaClass> classes) {
|
JavaPackage(PackageNode pkgNode, List<JavaClass> classes, List<JavaPackage> subPkgs) {
|
||||||
this.name = name;
|
this.pkgNode = pkgNode;
|
||||||
this.classes = classes;
|
this.classes = classes;
|
||||||
|
this.subPkgs = subPkgs;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return pkgNode.getAliasPkgInfo().getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getFullName() {
|
public String getFullName() {
|
||||||
// TODO: store full package name
|
return pkgNode.getAliasPkgInfo().getFullName();
|
||||||
return name;
|
}
|
||||||
|
|
||||||
|
public String getRawName() {
|
||||||
|
return pkgNode.getPkgInfo().getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRawFullName() {
|
||||||
|
return pkgNode.getPkgInfo().getFullName();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<JavaPackage> getSubPackages() {
|
||||||
|
return subPkgs;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<JavaClass> getClasses() {
|
public List<JavaClass> getClasses() {
|
||||||
return classes;
|
return classes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isRoot() {
|
||||||
|
return pkgNode.isRoot();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isLeaf() {
|
||||||
|
return pkgNode.isLeaf();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isDefault() {
|
||||||
|
return getFullName().isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void rename(String alias) {
|
||||||
|
pkgNode.rename(alias);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeAlias() {
|
||||||
|
pkgNode.removeAlias();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isParentRenamed() {
|
||||||
|
PackageInfo parent = pkgNode.getPkgInfo().getParentPkg();
|
||||||
|
PackageInfo aliasParent = pkgNode.getAliasPkgInfo().getParentPkg();
|
||||||
|
return !Objects.equals(parent, aliasParent);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ICodeNodeRef getCodeNodeRef() {
|
||||||
|
return pkgNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Internal
|
||||||
|
public PackageNode getPkgNode() {
|
||||||
|
return pkgNode;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JavaClass getDeclaringClass() {
|
public JavaClass getDeclaringClass() {
|
||||||
return null;
|
return null;
|
||||||
@@ -48,7 +103,16 @@ public final class JavaPackage implements JavaNode, Comparable<JavaPackage> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<JavaNode> getUseIn() {
|
public List<JavaNode> getUseIn() {
|
||||||
return Collections.emptyList();
|
List<JavaNode> list = new ArrayList<>();
|
||||||
|
addUseIn(list);
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addUseIn(List<JavaNode> list) {
|
||||||
|
list.addAll(classes);
|
||||||
|
for (JavaPackage subPkg : subPkgs) {
|
||||||
|
subPkg.addUseIn(list);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -58,7 +122,7 @@ public final class JavaPackage implements JavaNode, Comparable<JavaPackage> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int compareTo(@NotNull JavaPackage o) {
|
public int compareTo(@NotNull JavaPackage o) {
|
||||||
return name.compareTo(o.name);
|
return pkgNode.compareTo(o.pkgNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -70,16 +134,16 @@ public final class JavaPackage implements JavaNode, Comparable<JavaPackage> {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
JavaPackage that = (JavaPackage) o;
|
JavaPackage that = (JavaPackage) o;
|
||||||
return name.equals(that.name);
|
return pkgNode.equals(that.pkgNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return name.hashCode();
|
return pkgNode.hashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return name;
|
return pkgNode.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,8 +4,10 @@ import java.util.Collections;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.jetbrains.annotations.ApiStatus;
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import jadx.api.metadata.ICodeAnnotation;
|
import jadx.api.metadata.ICodeAnnotation;
|
||||||
|
import jadx.api.metadata.ICodeNodeRef;
|
||||||
import jadx.api.metadata.annotations.VarNode;
|
import jadx.api.metadata.annotations.VarNode;
|
||||||
import jadx.api.metadata.annotations.VarRef;
|
import jadx.api.metadata.annotations.VarRef;
|
||||||
import jadx.core.dex.instructions.args.ArgType;
|
import jadx.core.dex.instructions.args.ArgType;
|
||||||
@@ -32,10 +34,15 @@ public class JavaVariable implements JavaNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public @Nullable String getName() {
|
||||||
return varNode.getName();
|
return varNode.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ICodeNodeRef getCodeNodeRef() {
|
||||||
|
return varNode;
|
||||||
|
}
|
||||||
|
|
||||||
@ApiStatus.Internal
|
@ApiStatus.Internal
|
||||||
public VarNode getVarNode() {
|
public VarNode getVarNode() {
|
||||||
return varNode;
|
return varNode;
|
||||||
@@ -70,6 +77,11 @@ public class JavaVariable implements JavaNode {
|
|||||||
return Collections.singletonList(mth);
|
return Collections.singletonList(mth);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeAlias() {
|
||||||
|
varNode.setName(null);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isOwnCodeAnnotation(ICodeAnnotation ann) {
|
public boolean isOwnCodeAnnotation(ICodeAnnotation ann) {
|
||||||
if (ann.getAnnType() == ICodeAnnotation.AnnType.VAR_REF) {
|
if (ann.getAnnType() == ICodeAnnotation.AnnType.VAR_REF) {
|
||||||
|
|||||||
@@ -74,13 +74,20 @@ public class ResourceFile {
|
|||||||
this.zipRef = zipRef;
|
this.zipRef = zipRef;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAlias(ResourceEntry ri) {
|
public boolean setAlias(ResourceEntry ri) {
|
||||||
int index = name.lastIndexOf('.');
|
StringBuilder sb = new StringBuilder();
|
||||||
deobfName = String.format("res/%s%s/%s%s",
|
sb.append("res/").append(ri.getTypeName()).append(ri.getConfig());
|
||||||
ri.getTypeName(),
|
sb.append("/").append(ri.getKeyName());
|
||||||
ri.getConfig(),
|
int lastDot = name.lastIndexOf('.');
|
||||||
ri.getKeyName(),
|
if (lastDot != -1) {
|
||||||
index == -1 ? "" : name.substring(index));
|
sb.append(name.substring(lastDot));
|
||||||
|
}
|
||||||
|
String alias = sb.toString();
|
||||||
|
if (!alias.equals(name)) {
|
||||||
|
deobfName = alias;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ZipRef getZipRef() {
|
public ZipRef getZipRef() {
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import org.slf4j.LoggerFactory;
|
|||||||
|
|
||||||
import jadx.api.ResourceFile.ZipRef;
|
import jadx.api.ResourceFile.ZipRef;
|
||||||
import jadx.api.impl.SimpleCodeInfo;
|
import jadx.api.impl.SimpleCodeInfo;
|
||||||
|
import jadx.api.plugins.CustomResourcesLoader;
|
||||||
import jadx.api.plugins.utils.ZipSecurity;
|
import jadx.api.plugins.utils.ZipSecurity;
|
||||||
import jadx.core.dex.nodes.RootNode;
|
import jadx.core.dex.nodes.RootNode;
|
||||||
import jadx.core.utils.Utils;
|
import jadx.core.utils.Utils;
|
||||||
@@ -140,9 +141,23 @@ public final class ResourcesLoader {
|
|||||||
if (file == null || file.isDirectory()) {
|
if (file == null || file.isDirectory()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Try to load the resources with a custom loader first
|
||||||
|
for (CustomResourcesLoader loader : jadxRef.getCustomResourcesLoaders()) {
|
||||||
|
if (loader.load(this, list, file)) {
|
||||||
|
LOG.debug("Custom loader used for {}", file.getAbsolutePath());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If no custom decoder was able to decode the resources, use the default decoder
|
||||||
|
defaultLoadFile(list, file, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void defaultLoadFile(List<ResourceFile> list, File file, String subDir) {
|
||||||
if (FileUtils.isZipFile(file)) {
|
if (FileUtils.isZipFile(file)) {
|
||||||
ZipSecurity.visitZipEntries(file, (zipFile, entry) -> {
|
ZipSecurity.visitZipEntries(file, (zipFile, entry) -> {
|
||||||
addEntry(list, file, entry);
|
addEntry(list, file, entry, subDir);
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@@ -151,13 +166,13 @@ public final class ResourcesLoader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addEntry(List<ResourceFile> list, File zipFile, ZipEntry entry) {
|
public void addEntry(List<ResourceFile> list, File zipFile, ZipEntry entry, String subDir) {
|
||||||
if (entry.isDirectory()) {
|
if (entry.isDirectory()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
String name = entry.getName();
|
String name = entry.getName();
|
||||||
ResourceType type = ResourceType.getFileType(name);
|
ResourceType type = ResourceType.getFileType(name);
|
||||||
ResourceFile rf = ResourceFile.createResourceFile(jadxRef, name, type);
|
ResourceFile rf = ResourceFile.createResourceFile(jadxRef, subDir + name, type);
|
||||||
if (rf != null) {
|
if (rf != null) {
|
||||||
rf.setZipRef(new ZipRef(zipFile, name));
|
rf.setZipRef(new ZipRef(zipFile, name));
|
||||||
list.add(rf);
|
list.add(rf);
|
||||||
|
|||||||
+5
-1
@@ -1,6 +1,6 @@
|
|||||||
package jadx.api.args;
|
package jadx.api.args;
|
||||||
|
|
||||||
public enum DeobfuscationMapFileMode {
|
public enum GeneratedRenamesMappingFileMode {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load if found, don't save (default)
|
* Load if found, don't save (default)
|
||||||
@@ -22,6 +22,10 @@ public enum DeobfuscationMapFileMode {
|
|||||||
*/
|
*/
|
||||||
IGNORE;
|
IGNORE;
|
||||||
|
|
||||||
|
public static GeneratedRenamesMappingFileMode getDefault() {
|
||||||
|
return READ;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean shouldRead() {
|
public boolean shouldRead() {
|
||||||
return this == READ || this == READ_OR_SAVE;
|
return this == READ || this == READ_OR_SAVE;
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package jadx.api.args;
|
||||||
|
|
||||||
|
public enum IntegerFormat {
|
||||||
|
AUTO,
|
||||||
|
DECIMAL,
|
||||||
|
HEXADECIMAL;
|
||||||
|
|
||||||
|
public boolean isHexadecimal() {
|
||||||
|
return this == HEXADECIMAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package jadx.api.args;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resources original name source (for deobfuscation)
|
||||||
|
*/
|
||||||
|
public enum ResourceNameSource {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Automatically select best name (default)
|
||||||
|
*/
|
||||||
|
AUTO,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Force use resources provided names
|
||||||
|
*/
|
||||||
|
RESOURCES,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Force use resources names from R class
|
||||||
|
*/
|
||||||
|
CODE,
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
package jadx.api.args;
|
||||||
|
|
||||||
|
public enum UserRenamesMappingsMode {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Just read, user can save manually (default)
|
||||||
|
*/
|
||||||
|
READ,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read and autosave after every change
|
||||||
|
*/
|
||||||
|
READ_AND_AUTOSAVE_EVERY_CHANGE,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read and autosave before exiting the app or closing the project
|
||||||
|
*/
|
||||||
|
READ_AND_AUTOSAVE_BEFORE_CLOSING,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Don't load and don't save
|
||||||
|
*/
|
||||||
|
IGNORE;
|
||||||
|
|
||||||
|
public static UserRenamesMappingsMode getDefault() {
|
||||||
|
return READ;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean shouldRead() {
|
||||||
|
return this != IGNORE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean shouldWrite() {
|
||||||
|
return this == READ_AND_AUTOSAVE_EVERY_CHANGE || this == READ_AND_AUTOSAVE_BEFORE_CLOSING;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,4 +7,6 @@ public interface ICodeData {
|
|||||||
List<ICodeComment> getComments();
|
List<ICodeComment> getComments();
|
||||||
|
|
||||||
List<ICodeRename> getRenames();
|
List<ICodeRename> getRenames();
|
||||||
|
|
||||||
|
boolean isEmpty();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package jadx.api.data;
|
||||||
|
|
||||||
|
public interface IRenameNode {
|
||||||
|
|
||||||
|
void rename(String newName);
|
||||||
|
}
|
||||||
@@ -28,4 +28,9 @@ public class JadxCodeData implements ICodeData {
|
|||||||
public void setRenames(List<ICodeRename> renames) {
|
public void setRenames(List<ICodeRename> renames) {
|
||||||
this.renames = renames;
|
this.renames = renames;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return comments.isEmpty() && renames.isEmpty();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -85,4 +85,12 @@ public class JadxCodeRename implements ICodeRename {
|
|||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return 31 * getNodeRef().hashCode() + Objects.hashCode(getCodeRef());
|
return 31 * getNodeRef().hashCode() + Objects.hashCode(getCodeRef());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "JadxCodeRename{" + nodeRef
|
||||||
|
+ ", codeRef=" + codeRef
|
||||||
|
+ ", newName='" + newName + '\''
|
||||||
|
+ '}';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package jadx.api.deobf;
|
||||||
|
|
||||||
|
import jadx.core.dex.nodes.ClassNode;
|
||||||
|
import jadx.core.dex.nodes.FieldNode;
|
||||||
|
import jadx.core.dex.nodes.MethodNode;
|
||||||
|
import jadx.core.dex.nodes.PackageNode;
|
||||||
|
import jadx.core.dex.nodes.RootNode;
|
||||||
|
|
||||||
|
public interface IAliasProvider {
|
||||||
|
|
||||||
|
default void init(RootNode root) {
|
||||||
|
// optional
|
||||||
|
}
|
||||||
|
|
||||||
|
String forPackage(PackageNode pkg);
|
||||||
|
|
||||||
|
String forClass(ClassNode cls);
|
||||||
|
|
||||||
|
String forField(FieldNode fld);
|
||||||
|
|
||||||
|
String forMethod(MethodNode mth);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Optional method to set initial max indexes loaded from mapping
|
||||||
|
*/
|
||||||
|
default void initIndexes(int pkg, int cls, int fld, int mth) {
|
||||||
|
// optional
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package jadx.api.deobf;
|
||||||
|
|
||||||
|
import jadx.api.deobf.impl.CombineDeobfConditions;
|
||||||
|
import jadx.core.dex.nodes.ClassNode;
|
||||||
|
import jadx.core.dex.nodes.FieldNode;
|
||||||
|
import jadx.core.dex.nodes.MethodNode;
|
||||||
|
import jadx.core.dex.nodes.PackageNode;
|
||||||
|
import jadx.core.dex.nodes.RootNode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility interface to simplify merging several rename conditions to build {@link IRenameCondition}
|
||||||
|
* instance with {@link CombineDeobfConditions#combine(IDeobfCondition...)}.
|
||||||
|
*/
|
||||||
|
public interface IDeobfCondition {
|
||||||
|
|
||||||
|
enum Action {
|
||||||
|
NO_ACTION,
|
||||||
|
FORCE_RENAME,
|
||||||
|
FORBID_RENAME,
|
||||||
|
}
|
||||||
|
|
||||||
|
void init(RootNode root);
|
||||||
|
|
||||||
|
Action check(PackageNode pkg);
|
||||||
|
|
||||||
|
Action check(ClassNode cls);
|
||||||
|
|
||||||
|
Action check(FieldNode fld);
|
||||||
|
|
||||||
|
Action check(MethodNode mth);
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package jadx.api.deobf;
|
||||||
|
|
||||||
|
import jadx.core.dex.nodes.ClassNode;
|
||||||
|
import jadx.core.dex.nodes.FieldNode;
|
||||||
|
import jadx.core.dex.nodes.MethodNode;
|
||||||
|
import jadx.core.dex.nodes.PackageNode;
|
||||||
|
import jadx.core.dex.nodes.RootNode;
|
||||||
|
|
||||||
|
public interface IRenameCondition {
|
||||||
|
|
||||||
|
void init(RootNode root);
|
||||||
|
|
||||||
|
boolean shouldRename(PackageNode pkg);
|
||||||
|
|
||||||
|
boolean shouldRename(ClassNode cls);
|
||||||
|
|
||||||
|
boolean shouldRename(FieldNode fld);
|
||||||
|
|
||||||
|
boolean shouldRename(MethodNode mth);
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package jadx.api.deobf.impl;
|
||||||
|
|
||||||
|
import jadx.api.deobf.IRenameCondition;
|
||||||
|
import jadx.core.dex.nodes.ClassNode;
|
||||||
|
import jadx.core.dex.nodes.FieldNode;
|
||||||
|
import jadx.core.dex.nodes.MethodNode;
|
||||||
|
import jadx.core.dex.nodes.PackageNode;
|
||||||
|
import jadx.core.dex.nodes.RootNode;
|
||||||
|
|
||||||
|
public class AlwaysRename implements IRenameCondition {
|
||||||
|
|
||||||
|
public static final IRenameCondition INSTANCE = new AlwaysRename();
|
||||||
|
|
||||||
|
private AlwaysRename() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(RootNode root) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean shouldRename(PackageNode pkg) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean shouldRename(ClassNode cls) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean shouldRename(FieldNode fld) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean shouldRename(MethodNode mth) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
package jadx.api.deobf.impl;
|
||||||
|
|
||||||
|
import java.util.function.BiPredicate;
|
||||||
|
|
||||||
|
import jadx.api.deobf.IRenameCondition;
|
||||||
|
import jadx.core.dex.nodes.ClassNode;
|
||||||
|
import jadx.core.dex.nodes.FieldNode;
|
||||||
|
import jadx.core.dex.nodes.IDexNode;
|
||||||
|
import jadx.core.dex.nodes.MethodNode;
|
||||||
|
import jadx.core.dex.nodes.PackageNode;
|
||||||
|
import jadx.core.dex.nodes.RootNode;
|
||||||
|
|
||||||
|
public class AnyRenameCondition implements IRenameCondition {
|
||||||
|
|
||||||
|
private final BiPredicate<String, IDexNode> predicate;
|
||||||
|
|
||||||
|
public AnyRenameCondition(BiPredicate<String, IDexNode> predicate) {
|
||||||
|
this.predicate = predicate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(RootNode root) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean shouldRename(PackageNode pkg) {
|
||||||
|
return predicate.test(pkg.getAliasPkgInfo().getName(), pkg);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean shouldRename(ClassNode cls) {
|
||||||
|
return predicate.test(cls.getAlias(), cls);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean shouldRename(FieldNode fld) {
|
||||||
|
return predicate.test(fld.getAlias(), fld);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean shouldRename(MethodNode mth) {
|
||||||
|
return predicate.test(mth.getAlias(), mth);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
package jadx.api.deobf.impl;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
import jadx.api.deobf.IDeobfCondition;
|
||||||
|
import jadx.api.deobf.IRenameCondition;
|
||||||
|
import jadx.core.dex.nodes.ClassNode;
|
||||||
|
import jadx.core.dex.nodes.FieldNode;
|
||||||
|
import jadx.core.dex.nodes.MethodNode;
|
||||||
|
import jadx.core.dex.nodes.PackageNode;
|
||||||
|
import jadx.core.dex.nodes.RootNode;
|
||||||
|
|
||||||
|
public class CombineDeobfConditions implements IRenameCondition {
|
||||||
|
|
||||||
|
public static IRenameCondition combine(List<IDeobfCondition> conditions) {
|
||||||
|
return new CombineDeobfConditions(conditions);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IRenameCondition combine(IDeobfCondition... conditions) {
|
||||||
|
return new CombineDeobfConditions(Arrays.asList(conditions));
|
||||||
|
}
|
||||||
|
|
||||||
|
private final List<IDeobfCondition> conditions;
|
||||||
|
|
||||||
|
private CombineDeobfConditions(List<IDeobfCondition> conditions) {
|
||||||
|
if (conditions == null || conditions.isEmpty()) {
|
||||||
|
throw new IllegalArgumentException("Conditions list can't be empty");
|
||||||
|
}
|
||||||
|
this.conditions = conditions;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean combineFunc(Function<IDeobfCondition, IDeobfCondition.Action> check) {
|
||||||
|
for (IDeobfCondition c : conditions) {
|
||||||
|
switch (check.apply(c)) {
|
||||||
|
case NO_ACTION:
|
||||||
|
// ignore
|
||||||
|
break;
|
||||||
|
case FORCE_RENAME:
|
||||||
|
return true;
|
||||||
|
case FORBID_RENAME:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(RootNode root) {
|
||||||
|
conditions.forEach(c -> c.init(root));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean shouldRename(PackageNode pkg) {
|
||||||
|
return combineFunc(c -> c.check(pkg));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean shouldRename(ClassNode cls) {
|
||||||
|
return combineFunc(c -> c.check(cls));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean shouldRename(FieldNode fld) {
|
||||||
|
return combineFunc(c -> c.check(fld));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean shouldRename(MethodNode mth) {
|
||||||
|
return combineFunc(c -> c.check(mth));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -154,7 +154,6 @@ public class AnnotatedCodeWriter extends SimpleCodeWriter implements ICodeWriter
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ICodeInfo finish() {
|
public ICodeInfo finish() {
|
||||||
removeFirstEmptyLine();
|
|
||||||
processDefinitionAnnotations();
|
processDefinitionAnnotations();
|
||||||
validateAnnotations();
|
validateAnnotations();
|
||||||
String code = buf.toString();
|
String code = buf.toString();
|
||||||
|
|||||||
@@ -249,7 +249,6 @@ public class SimpleCodeWriter implements ICodeWriter {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getCodeStr() {
|
public String getCodeStr() {
|
||||||
removeFirstEmptyLine();
|
|
||||||
return buf.toString();
|
return buf.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,60 @@
|
|||||||
|
package jadx.api.impl.passes;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import jadx.api.plugins.pass.JadxPass;
|
||||||
|
import jadx.api.plugins.pass.types.JadxDecompilePass;
|
||||||
|
import jadx.core.dex.nodes.ClassNode;
|
||||||
|
import jadx.core.dex.nodes.MethodNode;
|
||||||
|
import jadx.core.dex.nodes.RootNode;
|
||||||
|
import jadx.core.dex.visitors.AbstractVisitor;
|
||||||
|
import jadx.core.utils.exceptions.JadxException;
|
||||||
|
|
||||||
|
public class DecompilePassWrapper extends AbstractVisitor implements IPassWrapperVisitor {
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(DecompilePassWrapper.class);
|
||||||
|
|
||||||
|
private final JadxDecompilePass decompilePass;
|
||||||
|
|
||||||
|
public DecompilePassWrapper(JadxDecompilePass decompilePass) {
|
||||||
|
this.decompilePass = decompilePass;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JadxPass getPass() {
|
||||||
|
return decompilePass;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(RootNode root) throws JadxException {
|
||||||
|
try {
|
||||||
|
decompilePass.init(root);
|
||||||
|
} catch (Throwable e) {
|
||||||
|
LOG.error("Error in decompile pass init: {}", this, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean visit(ClassNode cls) throws JadxException {
|
||||||
|
try {
|
||||||
|
return decompilePass.visit(cls);
|
||||||
|
} catch (Throwable e) {
|
||||||
|
LOG.error("Error in decompile pass: {}, class: {}", this, cls, e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(MethodNode mth) throws JadxException {
|
||||||
|
try {
|
||||||
|
decompilePass.visit(mth);
|
||||||
|
} catch (Throwable e) {
|
||||||
|
LOG.error("Error in decompile pass: {}, method: {}", this, mth, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return decompilePass.getInfo().getName();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package jadx.api.impl.passes;
|
||||||
|
|
||||||
|
import jadx.api.plugins.pass.JadxPass;
|
||||||
|
import jadx.core.dex.visitors.IDexTreeVisitor;
|
||||||
|
|
||||||
|
public interface IPassWrapperVisitor extends IDexTreeVisitor {
|
||||||
|
|
||||||
|
JadxPass getPass();
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package jadx.api.impl.passes;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import jadx.api.plugins.pass.JadxPass;
|
||||||
|
import jadx.api.plugins.pass.types.JadxPreparePass;
|
||||||
|
import jadx.core.dex.nodes.RootNode;
|
||||||
|
import jadx.core.dex.visitors.AbstractVisitor;
|
||||||
|
import jadx.core.utils.exceptions.JadxException;
|
||||||
|
|
||||||
|
public class PreparePassWrapper extends AbstractVisitor implements IPassWrapperVisitor {
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(PreparePassWrapper.class);
|
||||||
|
|
||||||
|
private final JadxPreparePass preparePass;
|
||||||
|
|
||||||
|
public PreparePassWrapper(JadxPreparePass preparePass) {
|
||||||
|
this.preparePass = preparePass;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JadxPass getPass() {
|
||||||
|
return preparePass;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(RootNode root) throws JadxException {
|
||||||
|
try {
|
||||||
|
preparePass.init(root);
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOG.error("Error in prepare pass init: {}", this, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return preparePass.getInfo().getName();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,10 +6,12 @@ public interface ICodeAnnotation {
|
|||||||
CLASS,
|
CLASS,
|
||||||
FIELD,
|
FIELD,
|
||||||
METHOD,
|
METHOD,
|
||||||
|
PKG,
|
||||||
VAR,
|
VAR,
|
||||||
VAR_REF,
|
VAR_REF,
|
||||||
DECLARATION,
|
DECLARATION,
|
||||||
OFFSET
|
OFFSET,
|
||||||
|
END // class or method body end
|
||||||
}
|
}
|
||||||
|
|
||||||
AnnType getAnnType();
|
AnnType getAnnType();
|
||||||
|
|||||||
@@ -32,6 +32,22 @@ public class NodeDeclareRef implements ICodeAnnotation {
|
|||||||
return AnnType.DECLARATION;
|
return AnnType.DECLARATION;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!(o instanceof NodeDeclareRef)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return node.equals(((NodeDeclareRef) o).node);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return node.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "NodeDeclareRef{" + node + '}';
|
return "NodeDeclareRef{" + node + '}';
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package jadx.api.metadata.annotations;
|
||||||
|
|
||||||
|
import jadx.api.metadata.ICodeAnnotation;
|
||||||
|
|
||||||
|
public class NodeEnd implements ICodeAnnotation {
|
||||||
|
|
||||||
|
public static final NodeEnd VALUE = new NodeEnd();
|
||||||
|
|
||||||
|
private NodeEnd() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AnnType getAnnType() {
|
||||||
|
return AnnType.END;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "END";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,16 +6,14 @@ import java.util.Map;
|
|||||||
import java.util.NavigableMap;
|
import java.util.NavigableMap;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
import java.util.function.BiFunction;
|
import java.util.function.BiFunction;
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import jadx.api.metadata.ICodeAnnotation;
|
import jadx.api.metadata.ICodeAnnotation;
|
||||||
|
import jadx.api.metadata.ICodeAnnotation.AnnType;
|
||||||
import jadx.api.metadata.ICodeMetadata;
|
import jadx.api.metadata.ICodeMetadata;
|
||||||
import jadx.api.metadata.ICodeNodeRef;
|
import jadx.api.metadata.ICodeNodeRef;
|
||||||
import jadx.api.metadata.annotations.NodeDeclareRef;
|
import jadx.api.metadata.annotations.NodeDeclareRef;
|
||||||
import jadx.core.dex.nodes.ClassNode;
|
|
||||||
import jadx.core.dex.nodes.MethodNode;
|
|
||||||
import jadx.core.utils.Utils;
|
import jadx.core.utils.Utils;
|
||||||
|
|
||||||
public class CodeMetadataStorage implements ICodeMetadata {
|
public class CodeMetadataStorage implements ICodeMetadata {
|
||||||
@@ -55,7 +53,7 @@ public class CodeMetadataStorage implements ICodeMetadata {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @Nullable ICodeAnnotation searchUp(int position, ICodeAnnotation.AnnType annType) {
|
public @Nullable ICodeAnnotation searchUp(int position, AnnType annType) {
|
||||||
for (ICodeAnnotation v : navMap.tailMap(position, true).values()) {
|
for (ICodeAnnotation v : navMap.tailMap(position, true).values()) {
|
||||||
if (v.getAnnType() == annType) {
|
if (v.getAnnType() == annType) {
|
||||||
return v;
|
return v;
|
||||||
@@ -65,7 +63,7 @@ public class CodeMetadataStorage implements ICodeMetadata {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @Nullable ICodeAnnotation searchUp(int position, int limitPos, ICodeAnnotation.AnnType annType) {
|
public @Nullable ICodeAnnotation searchUp(int position, int limitPos, AnnType annType) {
|
||||||
for (ICodeAnnotation v : navMap.subMap(position, true, limitPos, true).values()) {
|
for (ICodeAnnotation v : navMap.subMap(position, true, limitPos, true).values()) {
|
||||||
if (v.getAnnType() == annType) {
|
if (v.getAnnType() == annType) {
|
||||||
return v;
|
return v;
|
||||||
@@ -99,28 +97,40 @@ public class CodeMetadataStorage implements ICodeMetadata {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ICodeNodeRef getNodeAt(int position) {
|
public ICodeNodeRef getNodeAt(int position) {
|
||||||
return navMap.tailMap(position, true)
|
int nesting = 0;
|
||||||
.values().stream()
|
for (ICodeAnnotation ann : navMap.tailMap(position, true).values()) {
|
||||||
.flatMap(CodeMetadataStorage::mapEnclosingNode)
|
switch (ann.getAnnType()) {
|
||||||
.findFirst().orElse(null);
|
case END:
|
||||||
|
nesting++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DECLARATION:
|
||||||
|
ICodeNodeRef node = ((NodeDeclareRef) ann).getNode();
|
||||||
|
AnnType nodeType = node.getAnnType();
|
||||||
|
if (nodeType == AnnType.CLASS || nodeType == AnnType.METHOD) {
|
||||||
|
if (nesting == 0) {
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
nesting--;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ICodeNodeRef getNodeBelow(int position) {
|
public ICodeNodeRef getNodeBelow(int position) {
|
||||||
return navMap.headMap(position, true).descendingMap()
|
for (ICodeAnnotation ann : navMap.headMap(position, true).descendingMap().values()) {
|
||||||
.values().stream()
|
if (ann.getAnnType() == AnnType.DECLARATION) {
|
||||||
.flatMap(CodeMetadataStorage::mapEnclosingNode)
|
ICodeNodeRef node = ((NodeDeclareRef) ann).getNode();
|
||||||
.findFirst().orElse(null);
|
AnnType nodeType = node.getAnnType();
|
||||||
}
|
if (nodeType == AnnType.CLASS || nodeType == AnnType.METHOD) {
|
||||||
|
return node;
|
||||||
private static Stream<ICodeNodeRef> mapEnclosingNode(ICodeAnnotation ann) {
|
}
|
||||||
if (ann instanceof NodeDeclareRef) {
|
|
||||||
ICodeNodeRef node = ((NodeDeclareRef) ann).getNode();
|
|
||||||
if (node instanceof ClassNode || node instanceof MethodNode) {
|
|
||||||
return Stream.of(node);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Stream.empty();
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -135,7 +145,7 @@ public class CodeMetadataStorage implements ICodeMetadata {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "CodeMetadata{lines=" + lines
|
return "CodeMetadata{\nlines=" + lines
|
||||||
+ ", annotations=\n" + Utils.listToString(navMap.entrySet(), "\n") + "\n}";
|
+ "\nannotations=\n " + Utils.listToString(navMap.descendingMap().entrySet(), "\n ") + "\n}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package jadx.api.plugins;
|
||||||
|
|
||||||
|
import java.io.Closeable;
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import jadx.api.ResourceFile;
|
||||||
|
import jadx.api.ResourcesLoader;
|
||||||
|
|
||||||
|
public interface CustomResourcesLoader extends Closeable {
|
||||||
|
/**
|
||||||
|
* Load resources from file to list of ResourceFile
|
||||||
|
*
|
||||||
|
* @param list list to add loaded resources
|
||||||
|
* @param file file to load
|
||||||
|
* @return true if file was loaded
|
||||||
|
*/
|
||||||
|
boolean load(ResourcesLoader loader, List<ResourceFile> list, File file);
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package jadx.api.plugins;
|
||||||
|
|
||||||
|
import jadx.api.plugins.pass.types.JadxAfterLoadPass;
|
||||||
|
import jadx.api.plugins.pass.types.JadxPreparePass;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base interface for all jadx plugins
|
||||||
|
* <br>
|
||||||
|
* To create new plugin implement this interface and add to resources
|
||||||
|
* a {@code META-INF/services/jadx.api.plugins.JadxPlugin} file with a full name of your class.
|
||||||
|
*/
|
||||||
|
public interface JadxPlugin {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method for provide plugin information, like name and description.
|
||||||
|
* Can be invoked several times.
|
||||||
|
*/
|
||||||
|
JadxPluginInfo getPluginInfo();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Init plugin.
|
||||||
|
* Use {@link JadxPluginContext} to register passes, code inputs and options.
|
||||||
|
* For long operation, prefer {@link JadxPreparePass} or {@link JadxAfterLoadPass} instead.
|
||||||
|
*/
|
||||||
|
void init(JadxPluginContext context);
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
package jadx.api.plugins;
|
||||||
|
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import jadx.api.JadxArgs;
|
||||||
|
import jadx.api.JadxDecompiler;
|
||||||
|
import jadx.api.plugins.data.IJadxPlugins;
|
||||||
|
import jadx.api.plugins.events.IJadxEvents;
|
||||||
|
import jadx.api.plugins.gui.JadxGuiContext;
|
||||||
|
import jadx.api.plugins.input.JadxCodeInput;
|
||||||
|
import jadx.api.plugins.options.JadxPluginOptions;
|
||||||
|
import jadx.api.plugins.pass.JadxPass;
|
||||||
|
|
||||||
|
public interface JadxPluginContext {
|
||||||
|
|
||||||
|
JadxArgs getArgs();
|
||||||
|
|
||||||
|
JadxDecompiler getDecompiler();
|
||||||
|
|
||||||
|
void addPass(JadxPass pass);
|
||||||
|
|
||||||
|
void addCodeInput(JadxCodeInput codeInput);
|
||||||
|
|
||||||
|
void registerOptions(JadxPluginOptions options);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to calculate hash of all options which can change output code.
|
||||||
|
* Hash for input files ({@link JadxArgs#getInputFiles()}) and registered options
|
||||||
|
* calculated by default implementations.
|
||||||
|
*/
|
||||||
|
void registerInputsHashSupplier(Supplier<String> supplier);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access to jadx-gui specific methods
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
JadxGuiContext getGuiContext();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subscribe and send events
|
||||||
|
*/
|
||||||
|
IJadxEvents events();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access to registered plugins and runtime data
|
||||||
|
*/
|
||||||
|
IJadxPlugins plugins();
|
||||||
|
}
|
||||||
+12
-2
@@ -4,20 +4,26 @@ public class JadxPluginInfo {
|
|||||||
private final String pluginId;
|
private final String pluginId;
|
||||||
private final String name;
|
private final String name;
|
||||||
private final String description;
|
private final String description;
|
||||||
|
private final String homepage;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Conflicting plugins should have same 'provides' property, only one will be loaded
|
* Conflicting plugins should have the same 'provides' property; only one will be loaded
|
||||||
*/
|
*/
|
||||||
private final String provides;
|
private final String provides;
|
||||||
|
|
||||||
public JadxPluginInfo(String id, String name, String description) {
|
public JadxPluginInfo(String id, String name, String description) {
|
||||||
this(id, name, description, id);
|
this(id, name, description, "", id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public JadxPluginInfo(String pluginId, String name, String description, String provides) {
|
public JadxPluginInfo(String pluginId, String name, String description, String provides) {
|
||||||
|
this(pluginId, name, description, "", provides);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JadxPluginInfo(String pluginId, String name, String description, String homepage, String provides) {
|
||||||
this.pluginId = pluginId;
|
this.pluginId = pluginId;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.description = description;
|
this.description = description;
|
||||||
|
this.homepage = homepage;
|
||||||
this.provides = provides;
|
this.provides = provides;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,6 +39,10 @@ public class JadxPluginInfo {
|
|||||||
return description;
|
return description;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getHomepage() {
|
||||||
|
return homepage;
|
||||||
|
}
|
||||||
|
|
||||||
public String getProvides() {
|
public String getProvides() {
|
||||||
return provides;
|
return provides;
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
package jadx.api.plugins;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
public class JadxPluginInfoBuilder {
|
||||||
|
private String pluginId;
|
||||||
|
private String name;
|
||||||
|
private String description;
|
||||||
|
private String homepage = "";
|
||||||
|
private @Nullable String provides;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start building method
|
||||||
|
*/
|
||||||
|
public static JadxPluginInfoBuilder pluginId(String pluginId) {
|
||||||
|
JadxPluginInfoBuilder builder = new JadxPluginInfoBuilder();
|
||||||
|
builder.pluginId = Objects.requireNonNull(pluginId);
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
private JadxPluginInfoBuilder() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public JadxPluginInfoBuilder name(String name) {
|
||||||
|
this.name = Objects.requireNonNull(name);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JadxPluginInfoBuilder description(String description) {
|
||||||
|
this.description = Objects.requireNonNull(description);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JadxPluginInfoBuilder homepage(String homepage) {
|
||||||
|
this.homepage = homepage;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JadxPluginInfoBuilder provides(String provides) {
|
||||||
|
this.provides = provides;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JadxPluginInfo build() {
|
||||||
|
Objects.requireNonNull(pluginId, "PluginId is required");
|
||||||
|
Objects.requireNonNull(name, "Name is required");
|
||||||
|
Objects.requireNonNull(description, "Description is required");
|
||||||
|
if (provides == null) {
|
||||||
|
provides = pluginId;
|
||||||
|
}
|
||||||
|
return new JadxPluginInfo(pluginId, name, description, homepage, provides);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package jadx.api.plugins.data;
|
||||||
|
|
||||||
|
import jadx.api.plugins.JadxPlugin;
|
||||||
|
|
||||||
|
public interface IJadxPlugins {
|
||||||
|
|
||||||
|
JadxPluginRuntimeData getById(String pluginId);
|
||||||
|
|
||||||
|
JadxPluginRuntimeData getProviding(String provideId);
|
||||||
|
|
||||||
|
<P extends JadxPlugin> P getInstance(Class<P> pluginCls);
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package jadx.api.plugins.data;
|
||||||
|
|
||||||
|
import java.io.Closeable;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import jadx.api.plugins.JadxPlugin;
|
||||||
|
import jadx.api.plugins.JadxPluginInfo;
|
||||||
|
import jadx.api.plugins.input.ICodeLoader;
|
||||||
|
import jadx.api.plugins.input.JadxCodeInput;
|
||||||
|
import jadx.api.plugins.options.JadxPluginOptions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runtime plugin data.
|
||||||
|
*/
|
||||||
|
public interface JadxPluginRuntimeData {
|
||||||
|
boolean isInitialized();
|
||||||
|
|
||||||
|
String getPluginId();
|
||||||
|
|
||||||
|
JadxPlugin getPluginInstance();
|
||||||
|
|
||||||
|
JadxPluginInfo getPluginInfo();
|
||||||
|
|
||||||
|
List<JadxCodeInput> getCodeInputs();
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
JadxPluginOptions getOptions();
|
||||||
|
|
||||||
|
String getInputsHash();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convenient method to simplify code loading from custom files.
|
||||||
|
*/
|
||||||
|
ICodeLoader loadCodeFiles(List<Path> files, @Nullable Closeable closeable);
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package jadx.api.plugins.events;
|
||||||
|
|
||||||
|
public interface IJadxEvent {
|
||||||
|
|
||||||
|
JadxEventType<? extends IJadxEvent> getType();
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package jadx.api.plugins.events;
|
||||||
|
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
public interface IJadxEvents {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send an event object.
|
||||||
|
* For public event types check {@link JadxEvents} class.
|
||||||
|
*/
|
||||||
|
void send(IJadxEvent event);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register listener for specific event.
|
||||||
|
* For public event types check {@link JadxEvents} class.
|
||||||
|
*/
|
||||||
|
<E extends IJadxEvent> void addListener(JadxEventType<E> eventType, Consumer<E> listener);
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package jadx.api.plugins.events;
|
||||||
|
|
||||||
|
public abstract class JadxEventType<T extends IJadxEvent> {
|
||||||
|
|
||||||
|
public static <E extends IJadxEvent> JadxEventType<E> create() {
|
||||||
|
return new JadxEventType<>() {
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
package jadx.api.plugins.events;
|
||||||
|
|
||||||
|
import jadx.api.plugins.events.types.NodeRenamedByUser;
|
||||||
|
import jadx.api.plugins.events.types.ReloadProject;
|
||||||
|
import jadx.api.plugins.events.types.ReloadSettingsWindow;
|
||||||
|
import jadx.api.plugins.gui.ISettingsGroup;
|
||||||
|
import jadx.api.plugins.gui.JadxGuiSettings;
|
||||||
|
|
||||||
|
import static jadx.api.plugins.events.JadxEventType.create;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Typed and extendable enumeration of event types
|
||||||
|
*/
|
||||||
|
public class JadxEvents {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notify about renaming done by user (GUI only).
|
||||||
|
*/
|
||||||
|
public static final JadxEventType<NodeRenamedByUser> NODE_RENAMED_BY_USER = create();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request reload of a current project (GUI only).
|
||||||
|
*/
|
||||||
|
public static final JadxEventType<ReloadProject> RELOAD_PROJECT = create();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request reload of a settings window (GUI only).
|
||||||
|
* Useful for a reload custom settings group which was set with
|
||||||
|
* {@link JadxGuiSettings#setCustomSettingsGroup(ISettingsGroup)}.
|
||||||
|
*/
|
||||||
|
public static final JadxEventType<ReloadSettingsWindow> RELOAD_SETTINGS_WINDOW = create();
|
||||||
|
}
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
package jadx.api.plugins.events.types;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import jadx.api.metadata.ICodeNodeRef;
|
||||||
|
import jadx.api.plugins.events.IJadxEvent;
|
||||||
|
import jadx.api.plugins.events.JadxEventType;
|
||||||
|
import jadx.api.plugins.events.JadxEvents;
|
||||||
|
|
||||||
|
public class NodeRenamedByUser implements IJadxEvent {
|
||||||
|
|
||||||
|
private final ICodeNodeRef node;
|
||||||
|
private final String oldName;
|
||||||
|
private final String newName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Optional JRenameNode instance
|
||||||
|
*/
|
||||||
|
private @Nullable Object renameNode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request reset name to original
|
||||||
|
*/
|
||||||
|
private boolean resetName = false;
|
||||||
|
|
||||||
|
public NodeRenamedByUser(ICodeNodeRef node, String oldName, String newName) {
|
||||||
|
this.node = node;
|
||||||
|
this.oldName = oldName;
|
||||||
|
this.newName = newName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ICodeNodeRef getNode() {
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getOldName() {
|
||||||
|
return oldName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNewName() {
|
||||||
|
return newName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getRenameNode() {
|
||||||
|
return renameNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRenameNode(Object renameNode) {
|
||||||
|
this.renameNode = renameNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isResetName() {
|
||||||
|
return resetName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setResetName(boolean resetName) {
|
||||||
|
this.resetName = resetName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JadxEventType<NodeRenamedByUser> getType() {
|
||||||
|
return JadxEvents.NODE_RENAMED_BY_USER;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "NodeRenamedByUser{" + node
|
||||||
|
+ ", '" + oldName + "' -> '" + newName + '\''
|
||||||
|
+ (resetName ? ", reset name" : "")
|
||||||
|
+ '}';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package jadx.api.plugins.events.types;
|
||||||
|
|
||||||
|
import jadx.api.plugins.events.IJadxEvent;
|
||||||
|
import jadx.api.plugins.events.JadxEventType;
|
||||||
|
import jadx.api.plugins.events.JadxEvents;
|
||||||
|
|
||||||
|
public class ReloadProject implements IJadxEvent {
|
||||||
|
|
||||||
|
public static final ReloadProject EVENT = new ReloadProject();
|
||||||
|
|
||||||
|
private ReloadProject() {
|
||||||
|
// singleton
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JadxEventType<ReloadProject> getType() {
|
||||||
|
return JadxEvents.RELOAD_PROJECT;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "RELOAD_PROJECT";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package jadx.api.plugins.events.types;
|
||||||
|
|
||||||
|
import jadx.api.plugins.events.IJadxEvent;
|
||||||
|
import jadx.api.plugins.events.JadxEventType;
|
||||||
|
import jadx.api.plugins.events.JadxEvents;
|
||||||
|
|
||||||
|
public class ReloadSettingsWindow implements IJadxEvent {
|
||||||
|
|
||||||
|
public static final ReloadSettingsWindow INSTANCE = new ReloadSettingsWindow();
|
||||||
|
|
||||||
|
private ReloadSettingsWindow() {
|
||||||
|
// singleton
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JadxEventType<ReloadSettingsWindow> getType() {
|
||||||
|
return JadxEvents.RELOAD_SETTINGS_WINDOW;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "RELOAD_SETTINGS_WINDOW";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package jadx.api.plugins.gui;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.swing.JComponent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Settings page customization
|
||||||
|
*/
|
||||||
|
public interface ISettingsGroup {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Node name
|
||||||
|
*/
|
||||||
|
String getTitle();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Custom page component
|
||||||
|
*/
|
||||||
|
JComponent buildComponent();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Optional child nodes list
|
||||||
|
*/
|
||||||
|
default List<ISettingsGroup> getSubGroups() {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
package jadx.api.plugins.gui;
|
||||||
|
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
import javax.swing.KeyStroke;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import jadx.api.metadata.ICodeNodeRef;
|
||||||
|
|
||||||
|
public interface JadxGuiContext {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run code in UI Thread
|
||||||
|
*/
|
||||||
|
void uiRun(Runnable runnable);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add global menu entry ('Plugins' section)
|
||||||
|
*/
|
||||||
|
void addMenuAction(String name, Runnable action);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add code viewer popup menu entry
|
||||||
|
*
|
||||||
|
* @param name entry title
|
||||||
|
* @param enabled check if entry should be enabled, called on popup creation
|
||||||
|
* @param keyBinding optional assigned keybinding {@link KeyStroke#getKeyStroke(String)}
|
||||||
|
*/
|
||||||
|
void addPopupMenuAction(String name,
|
||||||
|
@Nullable Function<ICodeNodeRef, Boolean> enabled,
|
||||||
|
@Nullable String keyBinding,
|
||||||
|
Consumer<ICodeNodeRef> action);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attach new key binding to main window
|
||||||
|
*
|
||||||
|
* @param id unique ID string
|
||||||
|
* @param keyBinding keybinding string {@link KeyStroke#getKeyStroke(String)}
|
||||||
|
* @param action runnable action
|
||||||
|
* @return false if already registered
|
||||||
|
*/
|
||||||
|
boolean registerGlobalKeyBinding(String id, String keyBinding, Runnable action);
|
||||||
|
|
||||||
|
void copyToClipboard(String str);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access to GUI settings
|
||||||
|
*/
|
||||||
|
JadxGuiSettings settings();
|
||||||
|
|
||||||
|
ICodeNodeRef getNodeUnderCaret();
|
||||||
|
|
||||||
|
ICodeNodeRef getNodeUnderMouse();
|
||||||
|
|
||||||
|
ICodeNodeRef getEnclosingNodeUnderCaret();
|
||||||
|
|
||||||
|
ICodeNodeRef getEnclosingNodeUnderMouse();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Jump to a code ref
|
||||||
|
*
|
||||||
|
* @return if successfully jumped to the code ref
|
||||||
|
*/
|
||||||
|
boolean open(ICodeNodeRef ref);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reload code in active tab
|
||||||
|
*/
|
||||||
|
void reloadActiveTab();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reload code in all open tabs
|
||||||
|
*/
|
||||||
|
void reloadAllTabs();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save node rename in a project and run all needed UI updates
|
||||||
|
*/
|
||||||
|
void applyNodeRename(ICodeNodeRef node);
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package jadx.api.plugins.gui;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import jadx.api.plugins.options.OptionDescription;
|
||||||
|
|
||||||
|
public interface JadxGuiSettings {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set plugin custom settings page
|
||||||
|
*/
|
||||||
|
void setCustomSettingsGroup(ISettingsGroup group);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method to build options group only for provided option list
|
||||||
|
*/
|
||||||
|
ISettingsGroup buildSettingsGroupForOptions(String title, List<OptionDescription> options);
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package jadx.api.plugins.loader;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.ServiceLoader;
|
||||||
|
|
||||||
|
import jadx.api.plugins.JadxPlugin;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loading plugins from current classpath
|
||||||
|
*/
|
||||||
|
public class JadxBasePluginLoader implements JadxPluginLoader {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<JadxPlugin> load() {
|
||||||
|
List<JadxPlugin> list = new ArrayList<>();
|
||||||
|
ServiceLoader<JadxPlugin> plugins = ServiceLoader.load(JadxPlugin.class);
|
||||||
|
for (JadxPlugin plugin : plugins) {
|
||||||
|
list.add(plugin);
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() throws IOException {
|
||||||
|
// nothing to close
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package jadx.api.plugins.loader;
|
||||||
|
|
||||||
|
import java.io.Closeable;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import jadx.api.plugins.JadxPlugin;
|
||||||
|
|
||||||
|
public interface JadxPluginLoader extends Closeable {
|
||||||
|
|
||||||
|
List<JadxPlugin> load();
|
||||||
|
}
|
||||||
+1
-3
@@ -3,9 +3,7 @@ package jadx.api.plugins.options;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import jadx.api.plugins.JadxPlugin;
|
public interface JadxPluginOptions {
|
||||||
|
|
||||||
public interface JadxPluginOptions extends JadxPlugin {
|
|
||||||
|
|
||||||
void setOptions(Map<String, String> options);
|
void setOptions(Map<String, String> options);
|
||||||
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user