style: enforce code style using checkstyle and spotless with eclipse formatter (PR #650)
This commit is contained in:
+1
-5
@@ -7,14 +7,10 @@ insert_final_newline = true
|
||||
|
||||
indent_style = tab
|
||||
tab_width = 4
|
||||
continuation_indent_size = 8 #IntelliJ Idea specific workaround
|
||||
continuation_indent_size = 8 #IntelliJ Idea specific workaround
|
||||
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
max_line_length = 120
|
||||
|
||||
[*.xml]
|
||||
indent_size = 1
|
||||
|
||||
[*.yml]
|
||||
indent_style = space
|
||||
|
||||
@@ -10,6 +10,7 @@ out/
|
||||
*.ipr
|
||||
*.iws
|
||||
.attach_pid*
|
||||
*.hprof
|
||||
|
||||
**/.DS_Store
|
||||
|
||||
|
||||
+35
-12
@@ -1,7 +1,9 @@
|
||||
import com.diffplug.spotless.LineEnding
|
||||
|
||||
plugins {
|
||||
id 'org.sonarqube' version '2.7'
|
||||
id 'com.github.ben-manes.versions' version '0.21.0'
|
||||
id 'org.ec4j.editorconfig' version '0.0.3'
|
||||
id "com.diffplug.gradle.spotless" version "3.21.1"
|
||||
}
|
||||
|
||||
ext.jadxVersion = System.getenv('JADX_VERSION') ?: "dev"
|
||||
@@ -11,6 +13,7 @@ println("jadx version: ${jadxVersion}")
|
||||
allprojects {
|
||||
apply plugin: 'java'
|
||||
apply plugin: 'jacoco'
|
||||
apply plugin: 'checkstyle'
|
||||
|
||||
version = jadxVersion
|
||||
|
||||
@@ -67,6 +70,11 @@ allprojects {
|
||||
html.enabled = true
|
||||
}
|
||||
}
|
||||
|
||||
checkstyleMain {
|
||||
// exclude all sources in samples module
|
||||
exclude '**/samples/**'
|
||||
}
|
||||
}
|
||||
|
||||
sonarqube {
|
||||
@@ -76,14 +84,32 @@ sonarqube {
|
||||
}
|
||||
}
|
||||
|
||||
editorconfig {
|
||||
excludes = ['gradle/'
|
||||
, 'jadx-test-app/test-app' // ignore issues in submodule
|
||||
, '**/out/' // IntelliJ Idea build dirs
|
||||
, '**/certificate-test/' // binary test files (.RSA)
|
||||
, '**/*.svg'
|
||||
, '**/*.arsc'
|
||||
]
|
||||
spotless {
|
||||
java {
|
||||
target fileTree(rootDir).matching {
|
||||
include 'jadx-cli/src/**/java/**/*.java'
|
||||
include 'jadx-core/src/**/java/**/*.java'
|
||||
include 'jadx-gui/src/**/java/**/*.java'
|
||||
}
|
||||
|
||||
importOrderFile 'config/code-formatter/eclipse.importorder'
|
||||
eclipse().configFile 'config/code-formatter/eclipse.xml'
|
||||
removeUnusedImports()
|
||||
|
||||
lineEndings(LineEnding.UNIX)
|
||||
encoding("UTF-8")
|
||||
trimTrailingWhitespace()
|
||||
endWithNewline()
|
||||
}
|
||||
format 'misc', {
|
||||
target '**/*.gradle', '**/*.md', '**/*.xml', '**/.gitignore', '**/.properties'
|
||||
targetExclude "jadx-test-app/test-app/**", ".gradle/**", ".idea/**"
|
||||
|
||||
lineEndings(LineEnding.UNIX)
|
||||
encoding("UTF-8")
|
||||
trimTrailingWhitespace()
|
||||
endWithNewline()
|
||||
}
|
||||
}
|
||||
|
||||
dependencyUpdates.resolutionStrategy = {
|
||||
@@ -138,9 +164,6 @@ task cleanBuildDir(type: Delete) {
|
||||
delete buildDir
|
||||
}
|
||||
|
||||
check.dependsOn editorconfigCheck
|
||||
|
||||
test.dependsOn(samples)
|
||||
|
||||
clean.dependsOn(cleanBuildDir)
|
||||
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
<?xml version="1.0" ?>
|
||||
|
||||
<!DOCTYPE module PUBLIC
|
||||
"-//Puppy Crawl//DTD Check Configuration 1.2//EN"
|
||||
"http://www.puppycrawl.com/dtds/configuration_1_2.dtd">
|
||||
|
||||
<module name="Checker">
|
||||
<property name="fileExtensions" value="java, properties, xml"/>
|
||||
<property name="charset" value="UTF-8"/>
|
||||
|
||||
<module name="TreeWalker">
|
||||
<property name="tabWidth" value="4"/>
|
||||
<module name="RegexpSinglelineJava">
|
||||
<property name="format" value="^\t* "/>
|
||||
<property name="message" value="Indent must use tab characters"/>
|
||||
<property name="ignoreComments" value="true"/>
|
||||
</module>
|
||||
<module name="RegexpSinglelineJava">
|
||||
<property name="format" value="^(?!\s+\* $).*?\s+$"/>
|
||||
<property name="message" value="Line has trailing spaces."/>
|
||||
</module>
|
||||
<module name="AvoidEscapedUnicodeCharacters">
|
||||
<property name="allowEscapesForControlCharacters" value="true"/>
|
||||
<property name="allowByTailComment" value="true"/>
|
||||
<property name="allowNonPrintableEscapes" value="true"/>
|
||||
</module>
|
||||
|
||||
<module name="EmptyLineSeparator">
|
||||
<property name="allowNoEmptyLineBetweenFields" value="true"/>
|
||||
<property name="allowMultipleEmptyLines" value="false"/>
|
||||
</module>
|
||||
|
||||
<!-- whitespaces -->
|
||||
<module name="SingleSpaceSeparator"/>
|
||||
<module name="GenericWhitespace"/>
|
||||
<module name="MethodParamPad"/>
|
||||
<module name="NoWhitespaceBefore"/>
|
||||
<module name="OperatorWrap"/>
|
||||
<module name="ParenPad"/>
|
||||
<module name="TypecastParenPad"/>
|
||||
<module name="WhitespaceAfter"/>
|
||||
<module name="WhitespaceAround">
|
||||
<property name="allowEmptyMethods" value="true"/>
|
||||
</module>
|
||||
<!-- <module name="EmptyForIteratorPad"/> -->
|
||||
<!-- <module name="NoWhitespaceAfter"/>-->
|
||||
|
||||
<module name="NoLineWrap"/>
|
||||
|
||||
<module name="IllegalImport"/> <!-- defaults to sun.* packages -->
|
||||
<module name="RedundantImport"/>
|
||||
<module name="UnusedImports"/>
|
||||
<!-- <module name="AvoidStarImport"/> -->
|
||||
|
||||
<module name="NeedBraces"/>
|
||||
<module name="LeftCurly"/>
|
||||
<module name="RightCurly"/>
|
||||
<module name="EmptyCatchBlock">
|
||||
<property name="exceptionVariableName" value="expected|ignore"/>
|
||||
</module>
|
||||
|
||||
<!-- naming -->
|
||||
<module name="PackageName"/>
|
||||
<module name="TypeName"/>
|
||||
<module name="InterfaceTypeParameterName"/>
|
||||
<module name="ClassTypeParameterName"/>
|
||||
<module name="StaticVariableName"/>
|
||||
<module name="ConstantName"/>
|
||||
<module name="MemberName"/>
|
||||
<module name="MethodName"/>
|
||||
<module name="MethodTypeParameterName"/>
|
||||
<module name="ParameterName"/>
|
||||
<module name="LambdaParameterName"/>
|
||||
<module name="LocalVariableName"/>
|
||||
<module name="LocalFinalVariableName"/>
|
||||
<module name="CatchParameterName"/>
|
||||
<!-- <module name="HiddenField"/> -->
|
||||
|
||||
<!-- annotations -->
|
||||
<module name="AnnotationLocation"/>
|
||||
<module name="AnnotationUseStyle"/>
|
||||
<module name="MissingOverride"/>
|
||||
<!-- <module name="MissingDeprecated"/> -->
|
||||
|
||||
<module name="ModifierOrder"/>
|
||||
<!-- <module name="RedundantModifier"/> -->
|
||||
<!-- <module name="ParameterNumber"/> -->
|
||||
|
||||
<module name="EmptyStatement"/>
|
||||
<module name="DefaultComesLast"/>
|
||||
<module name="EqualsHashCode"/>
|
||||
<module name="FallThrough"/>
|
||||
<!-- <module name="IllegalCatch"/> -->
|
||||
<module name="IllegalThrows"/>
|
||||
<module name="IllegalType"/>
|
||||
<module name="InnerAssignment"/>
|
||||
<module name="MultipleVariableDeclarations"/>
|
||||
<module name="NoClone"/>
|
||||
<module name="NoFinalizer"/>
|
||||
<module name="OneStatementPerLine"/>
|
||||
<module name="PackageDeclaration"/>
|
||||
<module name="StringLiteralEquality"/>
|
||||
|
||||
<!-- misc -->
|
||||
<module name="ArrayTypeStyle"/>
|
||||
<module name="OuterTypeFilename"/>
|
||||
|
||||
<!-- sizes -->
|
||||
<module name="OuterTypeNumber"/>
|
||||
|
||||
<module name="SuppressWarningsHolder"/>
|
||||
</module>
|
||||
|
||||
<module name="NewlineAtEndOfFile"/>
|
||||
<module name="SuppressWarningsFilter"/>
|
||||
</module>
|
||||
@@ -0,0 +1,8 @@
|
||||
#Import Order
|
||||
0=java
|
||||
1=javax
|
||||
2=org
|
||||
3=com
|
||||
4=
|
||||
5=jadx
|
||||
6=\#
|
||||
@@ -0,0 +1,348 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<profiles version="16">
|
||||
<profile kind="CodeFormatterProfile" name="jadx eclipse" version="16">
|
||||
<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_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.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.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.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.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.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_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.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.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.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.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.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.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.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.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.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.insert_space_before_parenthesized_expression_in_return" value="insert"/>
|
||||
<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.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.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_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_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_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.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.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.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.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_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.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_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_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.line_length" value="100"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.use_on_off_tags" value="true"/>
|
||||
<setting id="org.eclipse.jdt.core.formatter.keep_method_body_on_one_line" value="one_line_never"/>
|
||||
<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.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.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.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.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.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_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.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_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.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_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.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_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.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_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_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.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.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.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.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_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_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_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_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.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.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.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.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_space_before_opening_brace_in_block" value="insert"/>
|
||||
<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_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_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_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_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.insert_space_between_empty_parens_in_constructor_declaration" value="do not insert"/>
|
||||
<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.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.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.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.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.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_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_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_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.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.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.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.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.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_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.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.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_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_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.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.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.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_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_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_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.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_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.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_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.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_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_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.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.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_before_opening_bracket_in_array_allocation_expression" value="do not insert"/>
|
||||
<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.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.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_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_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.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_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_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.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_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.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_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_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_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_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.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_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_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.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.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.blank_lines_between_import_groups" value="1"/>
|
||||
<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_before_opening_paren_in_switch" value="insert"/>
|
||||
</profile>
|
||||
</profiles>
|
||||
@@ -16,45 +16,46 @@ import com.beust.jcommander.Parameter;
|
||||
|
||||
import ch.qos.logback.classic.spi.ILoggingEvent;
|
||||
import ch.qos.logback.core.Appender;
|
||||
|
||||
import jadx.api.JadxArgs;
|
||||
import jadx.api.JadxArgs.RENAME;
|
||||
import jadx.api.JadxArgs.RenameEnum;
|
||||
import jadx.api.JadxDecompiler;
|
||||
import jadx.core.utils.exceptions.JadxException;
|
||||
import jadx.core.utils.files.FileUtils;
|
||||
|
||||
public class JadxCLIArgs {
|
||||
|
||||
@Parameter(description = "<input file> (.apk, .dex, .jar or .class)")
|
||||
@Parameter(description = "<input file> (.apk, .dex, .jar, .class, .smali, .zip, .aar, .arsc)")
|
||||
protected List<String> files = new ArrayList<>(1);
|
||||
|
||||
@Parameter(names = {"-d", "--output-dir"}, description = "output directory")
|
||||
@Parameter(names = { "-d", "--output-dir" }, description = "output directory")
|
||||
protected String outDir;
|
||||
|
||||
@Parameter(names = {"-ds", "--output-dir-src"}, description = "output directory for sources")
|
||||
@Parameter(names = { "-ds", "--output-dir-src" }, description = "output directory for sources")
|
||||
protected String outDirSrc;
|
||||
|
||||
@Parameter(names = {"-dr", "--output-dir-res"}, description = "output directory for resources")
|
||||
@Parameter(names = { "-dr", "--output-dir-res" }, description = "output directory for resources")
|
||||
protected String outDirRes;
|
||||
|
||||
@Parameter(names = {"-r", "--no-res"}, description = "do not decode resources")
|
||||
@Parameter(names = { "-r", "--no-res" }, description = "do not decode resources")
|
||||
protected boolean skipResources = false;
|
||||
|
||||
@Parameter(names = {"-s", "--no-src"}, description = "do not decompile source code")
|
||||
@Parameter(names = { "-s", "--no-src" }, description = "do not decompile source code")
|
||||
protected boolean skipSources = false;
|
||||
|
||||
@Parameter(names = {"-e", "--export-gradle"}, description = "save as android gradle project")
|
||||
@Parameter(names = { "-e", "--export-gradle" }, description = "save as android gradle project")
|
||||
protected boolean exportAsGradleProject = false;
|
||||
|
||||
@Parameter(names = {"-j", "--threads-count"}, description = "processing threads count")
|
||||
@Parameter(names = { "-j", "--threads-count" }, description = "processing threads count")
|
||||
protected int threadsCount = JadxArgs.DEFAULT_THREADS_COUNT;
|
||||
|
||||
@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;
|
||||
|
||||
@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;
|
||||
|
||||
@Parameter(names = {"--no-debug-info"}, description = "disable debug info")
|
||||
@Parameter(names = { "--no-debug-info" }, description = "disable debug info")
|
||||
protected boolean debugInfo = true;
|
||||
|
||||
@Parameter(names = { "--no-inline-anonymous" }, description = "disable anonymous classes inline")
|
||||
@@ -63,47 +64,54 @@ public class JadxCLIArgs {
|
||||
@Parameter(names = "--no-replace-consts", description = "don't replace constant value with matching constant field")
|
||||
protected boolean replaceConsts = true;
|
||||
|
||||
@Parameter(names = {"--escape-unicode"}, description = "escape non latin characters in strings (with \\u)")
|
||||
@Parameter(names = { "--escape-unicode" }, description = "escape non latin characters in strings (with \\u)")
|
||||
protected boolean escapeUnicode = false;
|
||||
|
||||
@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;
|
||||
|
||||
@Parameter(names = {"--deobf"}, description = "activate deobfuscation")
|
||||
@Parameter(names = { "--deobf" }, description = "activate deobfuscation")
|
||||
protected boolean deobfuscationOn = false;
|
||||
|
||||
@Parameter(names = {"--deobf-min"}, description = "min length of name, renamed if shorter")
|
||||
@Parameter(names = { "--deobf-min" }, description = "min length of name, renamed if shorter")
|
||||
protected int deobfuscationMinLength = 3;
|
||||
|
||||
@Parameter(names = {"--deobf-max"}, description = "max length of name, renamed if longer")
|
||||
@Parameter(names = { "--deobf-max" }, description = "max length of name, renamed if longer")
|
||||
protected int deobfuscationMaxLength = 64;
|
||||
|
||||
@Parameter(names = {"--deobf-rewrite-cfg"}, description = "force to save deobfuscation map")
|
||||
@Parameter(names = { "--deobf-rewrite-cfg" }, description = "force to save deobfuscation map")
|
||||
protected boolean deobfuscationForceSave = false;
|
||||
|
||||
@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 = true;
|
||||
|
||||
@Parameter(names = {"--cfg"}, description = "save methods control flow graph to dot file")
|
||||
@Parameter(names = { "--cfg" }, description = "save methods control flow graph to dot file")
|
||||
protected boolean cfgOutput = false;
|
||||
|
||||
@Parameter(names = {"--raw-cfg"}, description = "save methods control flow graph (use raw instructions)")
|
||||
@Parameter(names = { "--raw-cfg" }, description = "save methods control flow graph (use raw instructions)")
|
||||
protected boolean rawCfgOutput = false;
|
||||
|
||||
@Parameter(names = {"-f", "--fallback"}, description = "make simple dump (using goto instead of 'if', 'for', etc)")
|
||||
@Parameter(names = { "-f", "--fallback" }, description = "make simple dump (using goto instead of 'if', 'for', etc)")
|
||||
protected boolean fallbackMode = false;
|
||||
|
||||
@Parameter(names = {"--rename-flags"}, description = "what to rename, comma-separated, 'case' for system case sensitivity, 'valid' for java identifiers, 'printable' characters, 'none' or 'all'",
|
||||
converter = RenameConverter.class)
|
||||
protected Set<RENAME> renameFlags = EnumSet.allOf(RENAME.class);
|
||||
@Parameter(
|
||||
names = { "--rename-flags" },
|
||||
description = "what to rename, comma-separated,"
|
||||
+ " 'case' for system case sensitivity,"
|
||||
+ " 'valid' for java identifiers,"
|
||||
+ " 'printable' characters,"
|
||||
+ " 'none' or 'all'",
|
||||
converter = RenameConverter.class
|
||||
)
|
||||
protected Set<RenameEnum> renameFlags = EnumSet.allOf(RenameEnum.class);
|
||||
|
||||
@Parameter(names = {"-v", "--verbose"}, description = "verbose output")
|
||||
@Parameter(names = { "-v", "--verbose" }, description = "verbose output")
|
||||
protected boolean verbose = false;
|
||||
|
||||
@Parameter(names = {"--version"}, description = "print jadx version")
|
||||
@Parameter(names = { "--version" }, description = "print jadx version")
|
||||
protected boolean printVersion = false;
|
||||
|
||||
@Parameter(names = {"-h", "--help"}, description = "print this help", help = true)
|
||||
@Parameter(names = { "-h", "--help" }, description = "print this help", help = true)
|
||||
protected boolean printHelp = false;
|
||||
|
||||
public boolean processArgs(String[] args) {
|
||||
@@ -139,7 +147,7 @@ public class JadxCLIArgs {
|
||||
}
|
||||
if (verbose) {
|
||||
ch.qos.logback.classic.Logger rootLogger =
|
||||
(ch.qos.logback.classic.Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
|
||||
(ch.qos.logback.classic.Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
|
||||
// remove INFO ThresholdFilter
|
||||
Appender<ILoggingEvent> appender = rootLogger.getAppender("STDOUT");
|
||||
if (appender != null) {
|
||||
@@ -278,42 +286,42 @@ public class JadxCLIArgs {
|
||||
}
|
||||
|
||||
public boolean isRenameCaseSensitive() {
|
||||
return renameFlags.contains(RENAME.CASE);
|
||||
return renameFlags.contains(RenameEnum.CASE);
|
||||
}
|
||||
|
||||
public void setRenameCaseSensitive(boolean renameCase) {
|
||||
if (renameCase && !isRenameCaseSensitive()) {
|
||||
renameFlags.add(RENAME.CASE);
|
||||
renameFlags.add(RenameEnum.CASE);
|
||||
} else if (!renameCase && isRenameCaseSensitive()) {
|
||||
renameFlags.remove(RENAME.CASE);
|
||||
renameFlags.remove(RenameEnum.CASE);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isRenameValid() {
|
||||
return renameFlags.contains(RENAME.VALID);
|
||||
return renameFlags.contains(RenameEnum.VALID);
|
||||
}
|
||||
|
||||
public void setRenameValid(boolean renameValid) {
|
||||
if (renameValid && !isRenameValid()) {
|
||||
renameFlags.add(RENAME.VALID);
|
||||
renameFlags.add(RenameEnum.VALID);
|
||||
} else if (!renameValid && isRenameValid()) {
|
||||
renameFlags.remove(RENAME.VALID);
|
||||
renameFlags.remove(RenameEnum.VALID);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isRenamePrintable() {
|
||||
return renameFlags.contains(RENAME.PRINTABLE);
|
||||
return renameFlags.contains(RenameEnum.PRINTABLE);
|
||||
}
|
||||
|
||||
public void setRenamePrintable(boolean renamePrintable) {
|
||||
if (renamePrintable && !isRenamePrintable()) {
|
||||
renameFlags.add(RENAME.PRINTABLE);
|
||||
renameFlags.add(RenameEnum.PRINTABLE);
|
||||
} else if (!renamePrintable && isRenamePrintable()) {
|
||||
renameFlags.remove(RENAME.PRINTABLE);
|
||||
renameFlags.remove(RenameEnum.PRINTABLE);
|
||||
}
|
||||
}
|
||||
|
||||
static class RenameConverter implements IStringConverter<Set<RENAME>> {
|
||||
static class RenameConverter implements IStringConverter<Set<RenameEnum>> {
|
||||
|
||||
private final String paramName;
|
||||
|
||||
@@ -322,23 +330,23 @@ public class JadxCLIArgs {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<RENAME> convert(String value) {
|
||||
Set<RENAME> set = new HashSet<>();
|
||||
public Set<RenameEnum> convert(String value) {
|
||||
Set<RenameEnum> set = new HashSet<>();
|
||||
if (value.equalsIgnoreCase("ALL")) {
|
||||
set.add(RENAME.CASE);
|
||||
set.add(RENAME.VALID);
|
||||
set.add(RENAME.PRINTABLE);
|
||||
set.add(RenameEnum.CASE);
|
||||
set.add(RenameEnum.VALID);
|
||||
set.add(RenameEnum.PRINTABLE);
|
||||
} else if (!value.equalsIgnoreCase("NONE")) {
|
||||
for (String s : value.split(",")) {
|
||||
try {
|
||||
set.add(RENAME.valueOf(s.toUpperCase(Locale.ROOT)));
|
||||
set.add(RenameEnum.valueOf(s.toUpperCase(Locale.ROOT)));
|
||||
} catch (IllegalArgumentException e) {
|
||||
String values = "'" + RENAME.CASE
|
||||
+ "', '" + RENAME.VALID
|
||||
+ "' and '" + RENAME.PRINTABLE + '\'';
|
||||
String values = "'" + RenameEnum.CASE
|
||||
+ "', '" + RenameEnum.VALID
|
||||
+ "' and '" + RenameEnum.PRINTABLE + '\'';
|
||||
throw new IllegalArgumentException(
|
||||
s + " is unknown for parameter " + paramName
|
||||
+ ", possible values are " + values.toLowerCase(Locale.ROOT));
|
||||
+ ", possible values are " + values.toLowerCase(Locale.ROOT));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,8 +4,8 @@ import org.junit.jupiter.api.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
|
||||
public class JadxCLIArgsTest {
|
||||
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
package jadx.cli;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import jadx.api.JadxArgs.RENAME;
|
||||
import jadx.api.JadxArgs.RenameEnum;
|
||||
import jadx.cli.JadxCLIArgs.RenameConverter;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
public class RenameConverterTest {
|
||||
|
||||
private RenameConverter converter;
|
||||
@@ -23,16 +23,16 @@ public class RenameConverterTest {
|
||||
|
||||
@Test
|
||||
public void all() {
|
||||
Set<RENAME> set = converter.convert("all");
|
||||
Set<RenameEnum> set = converter.convert("all");
|
||||
assertEquals(3, set.size());
|
||||
assertTrue(set.contains(RENAME.CASE));
|
||||
assertTrue(set.contains(RENAME.VALID));
|
||||
assertTrue(set.contains(RENAME.PRINTABLE));
|
||||
assertTrue(set.contains(RenameEnum.CASE));
|
||||
assertTrue(set.contains(RenameEnum.VALID));
|
||||
assertTrue(set.contains(RenameEnum.PRINTABLE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void none() {
|
||||
Set<RENAME> set = converter.convert("none");
|
||||
Set<RenameEnum> set = converter.convert("none");
|
||||
assertTrue(set.isEmpty());
|
||||
}
|
||||
|
||||
|
||||
@@ -21,4 +21,3 @@ dependencies {
|
||||
testCompile 'com.google.guava:guava:27.1-jre'
|
||||
testCompile 'com.beust:jcommander:1.74'
|
||||
}
|
||||
|
||||
|
||||
@@ -50,9 +50,11 @@ public class JadxArgs {
|
||||
|
||||
private boolean fsCaseSensitive;
|
||||
|
||||
public enum RENAME {CASE, VALID, PRINTABLE}
|
||||
public enum RenameEnum {
|
||||
CASE, VALID, PRINTABLE
|
||||
}
|
||||
|
||||
private Set<RENAME> renameFlags = EnumSet.allOf(RENAME.class);
|
||||
private Set<RenameEnum> renameFlags = EnumSet.allOf(RenameEnum.class);
|
||||
|
||||
public JadxArgs() {
|
||||
// use default options
|
||||
@@ -261,66 +263,62 @@ public class JadxArgs {
|
||||
}
|
||||
|
||||
public boolean isRenameCaseSensitive() {
|
||||
return renameFlags.contains(RENAME.CASE);
|
||||
return renameFlags.contains(RenameEnum.CASE);
|
||||
}
|
||||
|
||||
public void setRenameCaseSensitive(boolean renameCaseSensitive) {
|
||||
if (renameCaseSensitive && !isRenameCaseSensitive()) {
|
||||
renameFlags.add(RENAME.CASE);
|
||||
} else if (!renameCaseSensitive && isRenameCaseSensitive()) {
|
||||
renameFlags.remove(RENAME.CASE);
|
||||
}
|
||||
updateRenameFlag(renameCaseSensitive, RenameEnum.CASE);
|
||||
}
|
||||
|
||||
public boolean isRenameValid() {
|
||||
return renameFlags.contains(RENAME.VALID);
|
||||
return renameFlags.contains(RenameEnum.VALID);
|
||||
}
|
||||
|
||||
public void setRenameValid(boolean renameValid) {
|
||||
if (renameValid && !isRenameValid()) {
|
||||
renameFlags.add(RENAME.VALID);
|
||||
} else if (!renameValid && isRenameValid()) {
|
||||
renameFlags.remove(RENAME.VALID);
|
||||
}
|
||||
updateRenameFlag(renameValid, RenameEnum.VALID);
|
||||
}
|
||||
|
||||
public boolean isRenamePrintable() {
|
||||
return renameFlags.contains(RENAME.PRINTABLE);
|
||||
return renameFlags.contains(RenameEnum.PRINTABLE);
|
||||
}
|
||||
|
||||
public void setRenamePrintable(boolean renamePrintable) {
|
||||
if (renamePrintable && !isRenamePrintable()) {
|
||||
renameFlags.add(RENAME.PRINTABLE);
|
||||
} else if (!renamePrintable && isRenamePrintable()) {
|
||||
renameFlags.remove(RENAME.PRINTABLE);
|
||||
updateRenameFlag(renamePrintable, RenameEnum.PRINTABLE);
|
||||
}
|
||||
|
||||
private void updateRenameFlag(boolean enabled, RenameEnum flag) {
|
||||
if (enabled) {
|
||||
renameFlags.add(flag);
|
||||
} else {
|
||||
renameFlags.remove(flag);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "JadxArgs{" + "inputFiles=" + inputFiles +
|
||||
", outDir=" + outDir +
|
||||
", outDirSrc=" + outDirSrc +
|
||||
", outDirRes=" + outDirRes +
|
||||
", threadsCount=" + threadsCount +
|
||||
", cfgOutput=" + cfgOutput +
|
||||
", rawCFGOutput=" + rawCFGOutput +
|
||||
", fallbackMode=" + fallbackMode +
|
||||
", showInconsistentCode=" + showInconsistentCode +
|
||||
", useImports=" + useImports +
|
||||
", skipResources=" + skipResources +
|
||||
", skipSources=" + skipSources +
|
||||
", deobfuscationOn=" + deobfuscationOn +
|
||||
", deobfuscationForceSave=" + deobfuscationForceSave +
|
||||
", useSourceNameAsClassAlias=" + useSourceNameAsClassAlias +
|
||||
", deobfuscationMinLength=" + deobfuscationMinLength +
|
||||
", deobfuscationMaxLength=" + deobfuscationMaxLength +
|
||||
", escapeUnicode=" + escapeUnicode +
|
||||
", replaceConsts=" + replaceConsts +
|
||||
", respectBytecodeAccModifiers=" + respectBytecodeAccModifiers +
|
||||
", exportAsGradleProject=" + exportAsGradleProject +
|
||||
", fsCaseSensitive=" + fsCaseSensitive +
|
||||
", renameFlags=" + renameFlags +
|
||||
'}';
|
||||
return "JadxArgs{" + "inputFiles=" + inputFiles
|
||||
+ ", outDir=" + outDir
|
||||
+ ", outDirSrc=" + outDirSrc
|
||||
+ ", outDirRes=" + outDirRes
|
||||
+ ", threadsCount=" + threadsCount
|
||||
+ ", cfgOutput=" + cfgOutput
|
||||
+ ", rawCFGOutput=" + rawCFGOutput
|
||||
+ ", fallbackMode=" + fallbackMode
|
||||
+ ", showInconsistentCode=" + showInconsistentCode
|
||||
+ ", useImports=" + useImports
|
||||
+ ", skipResources=" + skipResources
|
||||
+ ", skipSources=" + skipSources
|
||||
+ ", deobfuscationOn=" + deobfuscationOn
|
||||
+ ", deobfuscationForceSave=" + deobfuscationForceSave
|
||||
+ ", useSourceNameAsClassAlias=" + useSourceNameAsClassAlias
|
||||
+ ", deobfuscationMinLength=" + deobfuscationMinLength
|
||||
+ ", deobfuscationMaxLength=" + deobfuscationMaxLength
|
||||
+ ", escapeUnicode=" + escapeUnicode
|
||||
+ ", replaceConsts=" + replaceConsts
|
||||
+ ", respectBytecodeAccModifiers=" + respectBytecodeAccModifiers
|
||||
+ ", exportAsGradleProject=" + exportAsGradleProject
|
||||
+ ", fsCaseSensitive=" + fsCaseSensitive
|
||||
+ ", renameFlags=" + renameFlags
|
||||
+ '}';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
package jadx.api;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
@@ -15,20 +12,17 @@ import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.jf.baksmali.Adaptors.ClassDefinition;
|
||||
import org.jf.baksmali.Baksmali;
|
||||
import org.jf.baksmali.BaksmaliOptions;
|
||||
import org.jf.dexlib2.DexFileFactory;
|
||||
import org.jf.dexlib2.Opcodes;
|
||||
import org.jf.dexlib2.dexbacked.DexBackedClassDef;
|
||||
import org.jf.dexlib2.dexbacked.DexBackedDexFile;
|
||||
import org.jf.dexlib2.iface.ClassDef;
|
||||
import org.jf.util.IndentingWriter;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -44,15 +38,15 @@ import jadx.core.dex.visitors.IDexTreeVisitor;
|
||||
import jadx.core.dex.visitors.SaveCode;
|
||||
import jadx.core.export.ExportGradleProject;
|
||||
import jadx.core.utils.exceptions.JadxRuntimeException;
|
||||
import jadx.core.utils.files.DexFile;
|
||||
import jadx.core.utils.files.FileUtils;
|
||||
import jadx.core.utils.files.InputFile;
|
||||
import jadx.core.xmlgen.BinaryXMLParser;
|
||||
import jadx.core.xmlgen.ResourcesSaver;
|
||||
|
||||
/**
|
||||
* Jadx API usage example:
|
||||
* <pre><code>
|
||||
*
|
||||
* <pre>
|
||||
* <code>
|
||||
* JadxArgs args = new JadxArgs();
|
||||
* args.getInputFiles().add(new File("test.apk"));
|
||||
* args.setOutDir(new File("jadx-test-output"));
|
||||
@@ -60,14 +54,18 @@ import jadx.core.xmlgen.ResourcesSaver;
|
||||
* JadxDecompiler jadx = new JadxDecompiler(args);
|
||||
* jadx.load();
|
||||
* jadx.save();
|
||||
* </code></pre>
|
||||
* </code>
|
||||
* </pre>
|
||||
* <p>
|
||||
* Instead of 'save()' you can iterate over decompiled classes:
|
||||
* <pre><code>
|
||||
*
|
||||
* <pre>
|
||||
* <code>
|
||||
* for(JavaClass cls : jadx.getClasses()) {
|
||||
* System.out.println(cls.getCode());
|
||||
* }
|
||||
* </code></pre>
|
||||
* </code>
|
||||
* </pre>
|
||||
*/
|
||||
public final class JadxDecompiler {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(JadxDecompiler.class);
|
||||
|
||||
@@ -90,7 +90,7 @@ public final class ResourcesLoader {
|
||||
}
|
||||
|
||||
private static ResContainer loadContent(JadxDecompiler jadxRef, ResourceFile rf,
|
||||
InputStream inputStream) throws IOException {
|
||||
InputStream inputStream) throws IOException {
|
||||
switch (rf.getType()) {
|
||||
case MANIFEST:
|
||||
case XML:
|
||||
|
||||
@@ -49,7 +49,9 @@ public class ClsSet {
|
||||
|
||||
private static final NClass[] EMPTY_NCLASS_ARRAY = new NClass[0];
|
||||
|
||||
private enum ARG_TYPE {WILDCARD, GENERIC, GENERIC_TYPE, OBJECT, ARRAY, PRIMITIVE}
|
||||
private enum TypeEnum {
|
||||
WILDCARD, GENERIC, GENERIC_TYPE, OBJECT, ARRAY, PRIMITIVE
|
||||
}
|
||||
|
||||
private NClass[] classes;
|
||||
|
||||
@@ -97,12 +99,9 @@ public class ClsSet {
|
||||
List<ArgType> args = new ArrayList<>();
|
||||
|
||||
boolean genericArg = false;
|
||||
for (RegisterArg r: m.getArguments(false)) {
|
||||
for (RegisterArg r : m.getArguments(false)) {
|
||||
ArgType argType = r.getType();
|
||||
if (argType.isGeneric()) {
|
||||
args.add(argType);
|
||||
genericArg = true;
|
||||
} else if (argType.isGenericType()) {
|
||||
if (argType.isGeneric() || argType.isGenericType()) {
|
||||
args.add(argType);
|
||||
genericArg = true;
|
||||
} else {
|
||||
@@ -121,8 +120,8 @@ public class ClsSet {
|
||||
methods.add(new NMethod(
|
||||
m.getMethodInfo().getShortId(),
|
||||
args.isEmpty()
|
||||
? new ArgType[0]
|
||||
: args.toArray(new ArgType[args.size()]),
|
||||
? new ArgType[0]
|
||||
: args.toArray(new ArgType[args.size()]),
|
||||
retType,
|
||||
varArgs));
|
||||
}
|
||||
@@ -229,7 +228,7 @@ public class ClsSet {
|
||||
out.writeByte(argCount);
|
||||
|
||||
// last argument first
|
||||
for (int i = argTypes.length - 1; i >=0 ; i--) {
|
||||
for (int i = argTypes.length - 1; i >= 0; i--) {
|
||||
ArgType argType = argTypes[i];
|
||||
if (argType != null) {
|
||||
out.writeByte(i);
|
||||
@@ -249,14 +248,14 @@ public class ClsSet {
|
||||
|
||||
private static void writeArgType(DataOutputStream out, ArgType argType, Map<String, NClass> names) throws IOException {
|
||||
if (argType.getWildcardType() != null) {
|
||||
out.writeByte(ARG_TYPE.WILDCARD.ordinal());
|
||||
out.writeByte(TypeEnum.WILDCARD.ordinal());
|
||||
int bounds = argType.getWildcardBounds();
|
||||
out.writeByte(bounds);
|
||||
if (bounds != 0) {
|
||||
writeArgType(out, argType.getWildcardType(), names);
|
||||
}
|
||||
} else if (argType.isGeneric()) {
|
||||
out.writeByte(ARG_TYPE.GENERIC.ordinal());
|
||||
out.writeByte(TypeEnum.GENERIC.ordinal());
|
||||
out.writeInt(names.get(argType.getObject()).getId());
|
||||
ArgType[] types = argType.getGenericTypes();
|
||||
if (types == null) {
|
||||
@@ -268,16 +267,16 @@ public class ClsSet {
|
||||
}
|
||||
}
|
||||
} else if (argType.isGenericType()) {
|
||||
out.writeByte(ARG_TYPE.GENERIC_TYPE.ordinal());
|
||||
out.writeByte(TypeEnum.GENERIC_TYPE.ordinal());
|
||||
writeString(out, argType.getObject());
|
||||
} else if (argType.isObject()) {
|
||||
out.writeByte(ARG_TYPE.OBJECT.ordinal());
|
||||
out.writeByte(TypeEnum.OBJECT.ordinal());
|
||||
out.writeInt(names.get(argType.getObject()).getId());
|
||||
} else if (argType.isArray()) {
|
||||
out.writeByte(ARG_TYPE.ARRAY.ordinal());
|
||||
out.writeByte(TypeEnum.ARRAY.ordinal());
|
||||
writeArgType(out, argType.getArrayElement(), names);
|
||||
} else if (argType.isPrimitive()) {
|
||||
out.writeByte(ARG_TYPE.PRIMITIVE.ordinal());
|
||||
out.writeByte(TypeEnum.PRIMITIVE.ordinal());
|
||||
out.writeByte(argType.getPrimitiveType().getShortName().charAt(0));
|
||||
} else {
|
||||
throw new JadxRuntimeException("Cannot save type: " + argType);
|
||||
@@ -367,7 +366,7 @@ public class ClsSet {
|
||||
|
||||
private ArgType readArgType(DataInputStream in) throws IOException {
|
||||
int ordinal = in.readByte();
|
||||
switch(ARG_TYPE.values()[ordinal]) {
|
||||
switch (TypeEnum.values()[ordinal]) {
|
||||
case WILDCARD:
|
||||
int bounds = in.readByte();
|
||||
return bounds == 0
|
||||
@@ -394,25 +393,25 @@ public class ClsSet {
|
||||
return ArgType.array(readArgType(in));
|
||||
case PRIMITIVE:
|
||||
int shortName = in.readByte();
|
||||
switch(shortName) {
|
||||
case 'Z':
|
||||
return ArgType.BOOLEAN;
|
||||
case 'C':
|
||||
return ArgType.CHAR;
|
||||
case 'B':
|
||||
return ArgType.BYTE;
|
||||
case 'S':
|
||||
return ArgType.SHORT;
|
||||
case 'I':
|
||||
return ArgType.INT;
|
||||
case 'F':
|
||||
return ArgType.FLOAT;
|
||||
case 'J':
|
||||
return ArgType.LONG;
|
||||
case 'D':
|
||||
return ArgType.DOUBLE;
|
||||
default:
|
||||
return ArgType.VOID;
|
||||
switch (shortName) {
|
||||
case 'Z':
|
||||
return ArgType.BOOLEAN;
|
||||
case 'C':
|
||||
return ArgType.CHAR;
|
||||
case 'B':
|
||||
return ArgType.BYTE;
|
||||
case 'S':
|
||||
return ArgType.SHORT;
|
||||
case 'I':
|
||||
return ArgType.INT;
|
||||
case 'F':
|
||||
return ArgType.FLOAT;
|
||||
case 'J':
|
||||
return ArgType.LONG;
|
||||
case 'D':
|
||||
return ArgType.DOUBLE;
|
||||
default:
|
||||
return ArgType.VOID;
|
||||
}
|
||||
default:
|
||||
throw new JadxRuntimeException("Unsupported Arg Type: " + ordinal);
|
||||
|
||||
@@ -84,7 +84,7 @@ public class AnnotationGen {
|
||||
Map<String, Object> vl = a.getValues();
|
||||
if (!vl.isEmpty()) {
|
||||
code.add('(');
|
||||
for (Iterator<Entry<String, Object>> it = vl.entrySet().iterator(); it.hasNext(); ) {
|
||||
for (Iterator<Entry<String, Object>> it = vl.entrySet().iterator(); it.hasNext();) {
|
||||
Entry<String, Object> e = it.next();
|
||||
String paramName = getParamName(annCls, e.getKey());
|
||||
if (paramName.equals("value") && vl.size() == 1) {
|
||||
@@ -119,7 +119,7 @@ public class AnnotationGen {
|
||||
if (an != null) {
|
||||
Object exs = an.getDefaultValue();
|
||||
code.add(" throws ");
|
||||
for (Iterator<ArgType> it = ((List<ArgType>) exs).iterator(); it.hasNext(); ) {
|
||||
for (Iterator<ArgType> it = ((List<ArgType>) exs).iterator(); it.hasNext();) {
|
||||
ArgType ex = it.next();
|
||||
classGen.useType(code, ex);
|
||||
if (it.hasNext()) {
|
||||
|
||||
@@ -162,7 +162,7 @@ public class ClassGen {
|
||||
} else {
|
||||
clsCode.add("implements ");
|
||||
}
|
||||
for (Iterator<ArgType> it = cls.getInterfaces().iterator(); it.hasNext(); ) {
|
||||
for (Iterator<ArgType> it = cls.getInterfaces().iterator(); it.hasNext();) {
|
||||
ArgType interf = it.next();
|
||||
useClass(clsCode, interf);
|
||||
if (it.hasNext()) {
|
||||
@@ -194,7 +194,7 @@ public class ClassGen {
|
||||
}
|
||||
if (list != null && !list.isEmpty()) {
|
||||
code.add(" extends ");
|
||||
for (Iterator<ArgType> it = list.iterator(); it.hasNext(); ) {
|
||||
for (Iterator<ArgType> it = list.iterator(); it.hasNext();) {
|
||||
ArgType g = it.next();
|
||||
if (g.isGenericType()) {
|
||||
code.add(g.getObject());
|
||||
@@ -345,7 +345,7 @@ public class ClassGen {
|
||||
List<String> warns = node.getAll(AType.JADX_WARN);
|
||||
if (!warns.isEmpty()) {
|
||||
warns.stream().distinct().sorted()
|
||||
.forEach(warn -> code.startLine("/* JADX WARNING: ").addMultiLine(warn).add(" */"));
|
||||
.forEach(warn -> code.startLine("/* JADX WARNING: ").addMultiLine(warn).add(" */"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -399,7 +399,7 @@ public class ClassGen {
|
||||
return;
|
||||
}
|
||||
InsnGen igen = null;
|
||||
for (Iterator<EnumField> it = enumFields.getFields().iterator(); it.hasNext(); ) {
|
||||
for (Iterator<EnumField> it = enumFields.getFields().iterator(); it.hasNext();) {
|
||||
EnumField f = it.next();
|
||||
code.startLine(f.getField().getAlias());
|
||||
ConstructorInsn constrInsn = f.getConstrInsn();
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package jadx.core.codegen;
|
||||
|
||||
import static jadx.core.utils.android.AndroidResourcesUtils.handleAppResField;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumSet;
|
||||
import java.util.Iterator;
|
||||
@@ -56,6 +54,8 @@ import jadx.core.utils.RegionUtils;
|
||||
import jadx.core.utils.exceptions.CodegenException;
|
||||
import jadx.core.utils.exceptions.JadxRuntimeException;
|
||||
|
||||
import static jadx.core.utils.android.AndroidResourcesUtils.handleAppResField;
|
||||
|
||||
public class InsnGen {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(InsnGen.class);
|
||||
|
||||
@@ -234,8 +234,8 @@ public class InsnGen {
|
||||
code.add(';');
|
||||
}
|
||||
}
|
||||
} catch (Exception th) {
|
||||
throw new CodegenException(mth, "Error generate insn: " + insn, th);
|
||||
} catch (Exception e) {
|
||||
throw new CodegenException(mth, "Error generate insn: " + insn, e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -416,7 +416,7 @@ public class InsnGen {
|
||||
if (wrap) {
|
||||
code.add('(');
|
||||
}
|
||||
for (Iterator<InsnArg> it = insn.getArguments().iterator(); it.hasNext(); ) {
|
||||
for (Iterator<InsnArg> it = insn.getArguments().iterator(); it.hasNext();) {
|
||||
addArg(code, it.next());
|
||||
if (it.hasNext()) {
|
||||
code.add(" + ");
|
||||
@@ -701,7 +701,7 @@ public class InsnGen {
|
||||
}
|
||||
|
||||
void generateMethodArguments(CodeWriter code, InsnNode insn, int startArgNum,
|
||||
@Nullable MethodNode callMth) throws CodegenException {
|
||||
@Nullable MethodNode callMth) throws CodegenException {
|
||||
int k = startArgNum;
|
||||
if (callMth != null && callMth.contains(AFlag.SKIP_FIRST_ARG)) {
|
||||
k++;
|
||||
|
||||
@@ -3,10 +3,11 @@ package jadx.core.codegen;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import com.android.dx.rop.code.AccessFlags;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.android.dx.rop.code.AccessFlags;
|
||||
|
||||
import jadx.core.Consts;
|
||||
import jadx.core.dex.attributes.AFlag;
|
||||
import jadx.core.dex.attributes.AType;
|
||||
|
||||
@@ -50,8 +50,7 @@ public class NameGen {
|
||||
"java.lang.Long", "l",
|
||||
"java.lang.Double", "d",
|
||||
"java.lang.StringBuilder", "sb",
|
||||
"java.lang.Exception", "exc"
|
||||
);
|
||||
"java.lang.Exception", "exc");
|
||||
}
|
||||
|
||||
public NameGen(MethodNode mth, boolean fallback) {
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package jadx.core.deobf;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.file.Files;
|
||||
@@ -19,6 +17,8 @@ import jadx.core.dex.info.ClassInfo;
|
||||
import jadx.core.dex.info.FieldInfo;
|
||||
import jadx.core.dex.info.MethodInfo;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
class DeobfPresets {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(DeobfPresets.class);
|
||||
|
||||
|
||||
@@ -287,7 +287,8 @@ public class Deobfuscator {
|
||||
*
|
||||
* @param fullPkgName full package name
|
||||
* @param create if {@code true} then will create all absent objects
|
||||
* @return package node object or {@code null} if no package found and <b>create</b> set to {@code false}
|
||||
* @return package node object or {@code null} if no package found and <b>create</b> set to
|
||||
* {@code false}
|
||||
*/
|
||||
private PackageNode getPackageNode(String fullPkgName, boolean create) {
|
||||
if (fullPkgName.isEmpty() || fullPkgName.equals(CLASS_NAME_SEPARATOR)) {
|
||||
|
||||
@@ -69,9 +69,7 @@ public class NameMapper {
|
||||
"try",
|
||||
"void",
|
||||
"volatile",
|
||||
"while"
|
||||
)
|
||||
);
|
||||
"while"));
|
||||
|
||||
public static boolean isReserved(String str) {
|
||||
return RESERVED_NAMES.contains(str);
|
||||
@@ -113,15 +111,19 @@ public class NameMapper {
|
||||
|
||||
/**
|
||||
* Return modified string with removed:
|
||||
* <p><ul>
|
||||
* <li> not printable chars (including unicode)
|
||||
* <li> chars not valid for java identifier part
|
||||
* </ul><p>
|
||||
* <p>
|
||||
* <ul>
|
||||
* <li>not printable chars (including unicode)
|
||||
* <li>chars not valid for java identifier part
|
||||
* </ul>
|
||||
* <p>
|
||||
* Note: this 'middle' method must be used with prefixed string:
|
||||
* <p><ul>
|
||||
* <li> can leave invalid chars for java identifier start (i.e numbers)
|
||||
* <li> result not checked for reserved words
|
||||
* </ul><p>
|
||||
* <p>
|
||||
* <ul>
|
||||
* <li>can leave invalid chars for java identifier start (i.e numbers)
|
||||
* <li>result not checked for reserved words
|
||||
* </ul>
|
||||
* <p>
|
||||
*/
|
||||
public static String removeInvalidCharsMiddle(String name) {
|
||||
if (isValidIdentifier(name)) {
|
||||
|
||||
@@ -106,6 +106,7 @@ public final class ClassInfo implements Comparable<ClassInfo> {
|
||||
this.alias = newAlias;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isRenamed() {
|
||||
return alias != this;
|
||||
}
|
||||
|
||||
@@ -120,14 +120,13 @@ public class InsnDecoder {
|
||||
constStrInsn.setResult(InsnArg.reg(insn, 0, ArgType.STRING));
|
||||
return constStrInsn;
|
||||
|
||||
case Opcodes.CONST_CLASS:
|
||||
{
|
||||
case Opcodes.CONST_CLASS: {
|
||||
ArgType clsType = dex.getType(insn.getIndex());
|
||||
InsnNode constClsInsn = new ConstClassNode(clsType);
|
||||
constClsInsn.setResult(
|
||||
InsnArg.reg(insn, 0, ArgType.generic(Consts.CLASS_CLASS, clsType)));
|
||||
return constClsInsn;
|
||||
}
|
||||
}
|
||||
|
||||
case Opcodes.MOVE:
|
||||
case Opcodes.MOVE_16:
|
||||
|
||||
@@ -233,9 +233,9 @@ public abstract class ArgType {
|
||||
/**
|
||||
* Return wildcard bounds:
|
||||
* <ul>
|
||||
* <li> 1 for upper bound (? extends A) </li>
|
||||
* <li> 0 no bounds (?) </li>
|
||||
* <li>-1 for lower bound (? super A) </li>
|
||||
* <li>1 for upper bound (? extends A)</li>
|
||||
* <li>0 no bounds (?)</li>
|
||||
* <li>-1 for lower bound (? super A)</li>
|
||||
* </ul>
|
||||
*/
|
||||
@Override
|
||||
@@ -306,7 +306,7 @@ public abstract class ArgType {
|
||||
}
|
||||
|
||||
private static final class ArrayArg extends KnownType {
|
||||
private static final PrimitiveType[] ARRAY_POSSIBLES = new PrimitiveType[]{PrimitiveType.ARRAY};
|
||||
private static final PrimitiveType[] ARRAY_POSSIBLES = new PrimitiveType[] { PrimitiveType.ARRAY };
|
||||
private final ArgType arrayElement;
|
||||
|
||||
public ArrayArg(ArgType arrayElement) {
|
||||
|
||||
@@ -3,11 +3,12 @@ package jadx.core.dex.instructions.args;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.android.dx.io.instructions.DecodedInstruction;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.android.dx.io.instructions.DecodedInstruction;
|
||||
|
||||
import jadx.core.dex.attributes.AFlag;
|
||||
import jadx.core.dex.nodes.InsnNode;
|
||||
import jadx.core.utils.InsnUtils;
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package jadx.core.dex.nodes;
|
||||
|
||||
import static jadx.core.dex.nodes.ProcessState.UNLOADED;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
@@ -38,6 +36,8 @@ import jadx.core.dex.nodes.parser.StaticValuesParser;
|
||||
import jadx.core.utils.exceptions.DecodeException;
|
||||
import jadx.core.utils.exceptions.JadxRuntimeException;
|
||||
|
||||
import static jadx.core.dex.nodes.ProcessState.UNLOADED;
|
||||
|
||||
public class ClassNode extends LineAttrNode implements ILoadable, ICodeNode {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ClassNode.class);
|
||||
|
||||
@@ -355,7 +355,8 @@ public class ClassNode extends LineAttrNode implements ILoadable, ICodeNode {
|
||||
|
||||
/**
|
||||
* Return first method by original short name
|
||||
* Note: methods are not unique by name (class can have several methods with same name but different signature)
|
||||
* Note: methods are not unique by name (class can have several methods with same name but different
|
||||
* signature)
|
||||
*/
|
||||
@Nullable
|
||||
public MethodNode searchMethodByShortName(String name) {
|
||||
|
||||
@@ -7,6 +7,9 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.android.dex.ClassData;
|
||||
import com.android.dex.ClassData.Method;
|
||||
import com.android.dex.ClassDef;
|
||||
@@ -17,8 +20,6 @@ import com.android.dex.FieldId;
|
||||
import com.android.dex.MethodId;
|
||||
import com.android.dex.ProtoId;
|
||||
import com.android.dex.TypeList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import jadx.core.dex.info.ClassInfo;
|
||||
import jadx.core.dex.info.FieldInfo;
|
||||
|
||||
@@ -8,4 +8,3 @@ public interface IDexNode {
|
||||
|
||||
RootNode root();
|
||||
}
|
||||
|
||||
|
||||
@@ -7,15 +7,16 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.android.dex.ClassData.Method;
|
||||
import com.android.dex.Code;
|
||||
import com.android.dex.Code.CatchHandler;
|
||||
import com.android.dex.Code.Try;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.android.dex.ClassData.Method;
|
||||
import com.android.dex.Code;
|
||||
import com.android.dex.Code.CatchHandler;
|
||||
import com.android.dex.Code.Try;
|
||||
|
||||
import jadx.core.dex.attributes.AFlag;
|
||||
import jadx.core.dex.attributes.AType;
|
||||
import jadx.core.dex.attributes.nodes.JumpInfo;
|
||||
@@ -154,7 +155,7 @@ public class MethodNode extends LineAttrNode implements ILoadable, ICodeNode {
|
||||
for (RegisterArg arg : list) {
|
||||
if (arg.getRegNum() >= regsCount) {
|
||||
throw new JadxRuntimeException("Incorrect register number in instruction: " + insnNode
|
||||
+ ", expected to be less than " + regsCount);
|
||||
+ ", expected to be less than " + regsCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -234,26 +234,25 @@ public final class IfCondition {
|
||||
if (arithOp == ArithOp.OR || arithOp == ArithOp.AND) {
|
||||
IfOp ifOp = c.getInsn().getOp();
|
||||
boolean isTrue = ifOp == IfOp.NE && lit == 0
|
||||
|| ifOp == IfOp.EQ && lit == 1;
|
||||
|| ifOp == IfOp.EQ && lit == 1;
|
||||
|
||||
IfOp op = isTrue ? IfOp.NE : IfOp.EQ;
|
||||
Mode mode = isTrue && arithOp == ArithOp.OR ||
|
||||
!isTrue && arithOp == ArithOp.AND ? Mode.OR : Mode.AND;
|
||||
Mode mode = isTrue && arithOp == ArithOp.OR
|
||||
|| !isTrue && arithOp == ArithOp.AND ? Mode.OR : Mode.AND;
|
||||
|
||||
IfNode if1 = new IfNode(op, -1, wrapInsn.getArg(0), LiteralArg.FALSE);
|
||||
IfNode if2 = new IfNode(op, -1, wrapInsn.getArg(1), LiteralArg.FALSE);
|
||||
return new IfCondition(mode,
|
||||
Arrays.asList(new IfCondition(new Compare(if1)),
|
||||
new IfCondition(new Compare(if2))));
|
||||
Arrays.asList(new IfCondition(new Compare(if1)),
|
||||
new IfCondition(new Compare(if2))));
|
||||
}
|
||||
}
|
||||
break;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -300,7 +299,7 @@ public final class IfCondition {
|
||||
String op = mode == Mode.OR ? " || " : " && ";
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append('(');
|
||||
for (Iterator<IfCondition> it = args.iterator(); it.hasNext(); ) {
|
||||
for (Iterator<IfCondition> it = args.iterator(); it.hasNext();) {
|
||||
IfCondition arg = it.next();
|
||||
sb.append(arg);
|
||||
if (it.hasNext()) {
|
||||
@@ -326,7 +325,7 @@ public final class IfCondition {
|
||||
return false;
|
||||
}
|
||||
return Objects.equals(args, other.args)
|
||||
&& Objects.equals(compare, other.compare);
|
||||
&& Objects.equals(compare, other.compare);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -24,7 +24,7 @@ public final class IfInfo {
|
||||
}
|
||||
|
||||
private IfInfo(IfCondition condition, BlockNode thenBlock, BlockNode elseBlock,
|
||||
Set<BlockNode> mergedBlocks, Set<BlockNode> skipBlocks) {
|
||||
Set<BlockNode> mergedBlocks, Set<BlockNode> skipBlocks) {
|
||||
this.condition = condition;
|
||||
this.thenBlock = thenBlock;
|
||||
this.elseBlock = elseBlock;
|
||||
|
||||
@@ -147,14 +147,14 @@ public class ExceptionHandler {
|
||||
return false;
|
||||
}
|
||||
ExceptionHandler that = (ExceptionHandler) o;
|
||||
return handleOffset == that.handleOffset &&
|
||||
catchTypes.equals(that.catchTypes) &&
|
||||
Objects.equals(tryBlock, that.tryBlock);
|
||||
return handleOffset == that.handleOffset
|
||||
&& catchTypes.equals(that.catchTypes)
|
||||
&& Objects.equals(tryBlock, that.tryBlock);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(catchTypes, handleOffset /*, tryBlock*/);
|
||||
return Objects.hash(catchTypes, handleOffset /* , tryBlock */);
|
||||
}
|
||||
|
||||
public String catchTypeStr() {
|
||||
|
||||
@@ -53,7 +53,7 @@ public class TryCatchBlock {
|
||||
}
|
||||
|
||||
public void removeHandler(MethodNode mth, ExceptionHandler handler) {
|
||||
for (Iterator<ExceptionHandler> it = handlers.iterator(); it.hasNext(); ) {
|
||||
for (Iterator<ExceptionHandler> it = handlers.iterator(); it.hasNext();) {
|
||||
ExceptionHandler h = it.next();
|
||||
if (h == handler) {
|
||||
unbindHandler(h);
|
||||
@@ -85,7 +85,7 @@ public class TryCatchBlock {
|
||||
|
||||
private void removeWholeBlock(MethodNode mth) {
|
||||
// self destruction
|
||||
for (Iterator<ExceptionHandler> it = handlers.iterator(); it.hasNext(); ) {
|
||||
for (Iterator<ExceptionHandler> it = handlers.iterator(); it.hasNext();) {
|
||||
ExceptionHandler h = it.next();
|
||||
unbindHandler(h);
|
||||
it.remove();
|
||||
|
||||
@@ -5,7 +5,7 @@ import jadx.core.dex.nodes.MethodNode;
|
||||
import jadx.core.dex.nodes.RootNode;
|
||||
import jadx.core.utils.exceptions.JadxException;
|
||||
|
||||
public class AbstractVisitor implements IDexTreeVisitor {
|
||||
public abstract class AbstractVisitor implements IDexTreeVisitor {
|
||||
|
||||
@Override
|
||||
public void init(RootNode root) throws JadxException {
|
||||
|
||||
@@ -34,7 +34,7 @@ import jadx.core.utils.exceptions.JadxException;
|
||||
@JadxVisitor(
|
||||
name = "EnumVisitor",
|
||||
desc = "Restore enum classes",
|
||||
runAfter = {CodeShrinkVisitor.class, ModVisitor.class}
|
||||
runAfter = { CodeShrinkVisitor.class, ModVisitor.class }
|
||||
)
|
||||
public class EnumVisitor extends AbstractVisitor {
|
||||
|
||||
|
||||
@@ -59,8 +59,8 @@ public class MarkFinallyVisitor extends AbstractVisitor {
|
||||
visitor.init(mth.root());
|
||||
DepthTraversal.visit(visitor, mth);
|
||||
}
|
||||
} catch (Exception ee) {
|
||||
LOG.error("Undo finally extract failed, mth: {}", mth, e);
|
||||
} catch (Exception excInner) {
|
||||
LOG.error("Undo finally extract failed, mth: {}", mth, excInner);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -343,7 +343,7 @@ public class MarkFinallyVisitor extends AbstractVisitor {
|
||||
return null;
|
||||
}
|
||||
// TODO: add additional slices checks
|
||||
// and try to extract common part if found difference
|
||||
// and try to extract common part if found difference
|
||||
} else {
|
||||
for (InsnNode finallyInsn : finallyInsns) {
|
||||
finallySlice.addInsn(finallyInsn, finallyBlock);
|
||||
@@ -369,7 +369,7 @@ public class MarkFinallyVisitor extends AbstractVisitor {
|
||||
}
|
||||
|
||||
private static boolean checkBlocksTree(BlockNode dupBlock, BlockNode finallyBlock,
|
||||
InsnsSlice dupSlice, FinallyExtractInfo extractInfo) {
|
||||
InsnsSlice dupSlice, FinallyExtractInfo extractInfo) {
|
||||
InsnsSlice finallySlice = extractInfo.getFinallyInsnsSlice();
|
||||
|
||||
List<BlockNode> finallyCS = finallyBlock.getCleanSuccessors();
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package jadx.core.dex.visitors;
|
||||
|
||||
import static jadx.core.utils.BlockUtils.replaceInsn;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
@@ -48,6 +46,8 @@ import jadx.core.utils.InsnRemover;
|
||||
import jadx.core.utils.InsnUtils;
|
||||
import jadx.core.utils.exceptions.JadxRuntimeException;
|
||||
|
||||
import static jadx.core.utils.BlockUtils.replaceInsn;
|
||||
|
||||
/**
|
||||
* Visitor for modify method instructions
|
||||
* (remove, replace, process exception handlers)
|
||||
@@ -168,8 +168,9 @@ public class ModVisitor extends AbstractVisitor {
|
||||
IfCondition condition = IfCondition.fromIfNode(ifNode);
|
||||
InsnArg zero = new LiteralArg(0, type);
|
||||
InsnArg one = new LiteralArg(
|
||||
type == ArgType.DOUBLE ? Double.doubleToLongBits(1) :
|
||||
type == ArgType.FLOAT ? Float.floatToIntBits(1) : 1, type);
|
||||
type == ArgType.DOUBLE ? Double.doubleToLongBits(1)
|
||||
: type == ArgType.FLOAT ? Float.floatToIntBits(1) : 1,
|
||||
type);
|
||||
TernaryInsn ternary = new TernaryInsn(condition, insn.getResult(), one, zero);
|
||||
replaceInsn(block, i, ternary);
|
||||
}
|
||||
@@ -325,8 +326,7 @@ public class ModVisitor extends AbstractVisitor {
|
||||
if (!elType.equals(insnElementType) && !insnArrayType.equals(ArgType.OBJECT)) {
|
||||
ErrorsCounter.methodWarn(mth,
|
||||
"Incorrect type for fill-array insn " + InsnUtils.formatOffset(insn.getOffset())
|
||||
+ ", element type: " + elType + ", insn element type: " + insnElementType
|
||||
);
|
||||
+ ", element type: " + elType + ", insn element type: " + insnElementType);
|
||||
}
|
||||
if (!elType.isTypeKnown()) {
|
||||
LOG.warn("Unknown array element type: {} in mth: {}", elType, mth);
|
||||
|
||||
@@ -29,7 +29,7 @@ import jadx.core.utils.exceptions.JadxException;
|
||||
@JadxVisitor(
|
||||
name = "PrepareForCodeGen",
|
||||
desc = "Prepare instructions for code generation pass",
|
||||
runAfter = {CodeShrinkVisitor.class, ClassModifier.class, ProcessVariables.class}
|
||||
runAfter = { CodeShrinkVisitor.class, ClassModifier.class, ProcessVariables.class }
|
||||
)
|
||||
public class PrepareForCodeGen extends AbstractVisitor {
|
||||
|
||||
@@ -70,8 +70,7 @@ public class PrepareForCodeGen extends AbstractVisitor {
|
||||
break;
|
||||
|
||||
case MOVE:
|
||||
// remove redundant moves:
|
||||
// unused result and same args names (a = a;)
|
||||
// remove redundant moves: unused result and same args names (a = a;)
|
||||
RegisterArg result = insn.getResult();
|
||||
if (result.getSVar().getUseCount() == 0
|
||||
&& result.isNameEquals(insn.getArg(0))) {
|
||||
|
||||
@@ -32,8 +32,8 @@ import jadx.core.dex.nodes.InsnNode;
|
||||
import jadx.core.dex.nodes.MethodNode;
|
||||
import jadx.core.dex.visitors.shrink.CodeShrinkVisitor;
|
||||
import jadx.core.utils.InsnList;
|
||||
import jadx.core.utils.InsnUtils;
|
||||
import jadx.core.utils.InsnRemover;
|
||||
import jadx.core.utils.InsnUtils;
|
||||
import jadx.core.utils.Utils;
|
||||
import jadx.core.utils.exceptions.JadxException;
|
||||
|
||||
@@ -92,7 +92,7 @@ public class ReSugarCode extends AbstractVisitor {
|
||||
* Replace new array and sequence of array-put to new filled-array instruction.
|
||||
*/
|
||||
private static void processNewArray(MethodNode mth, NewArrayNode newArrayInsn,
|
||||
List<InsnNode> instructions, InsnRemover remover) {
|
||||
List<InsnNode> instructions, InsnRemover remover) {
|
||||
InsnArg arrLenArg = newArrayInsn.getArg(0);
|
||||
if (!arrLenArg.isLiteral()) {
|
||||
return;
|
||||
|
||||
@@ -10,7 +10,8 @@ import jadx.core.utils.exceptions.JadxRuntimeException;
|
||||
|
||||
public class SaveCode {
|
||||
|
||||
private SaveCode() {}
|
||||
private SaveCode() {
|
||||
}
|
||||
|
||||
public static void save(File dir, JadxArgs args, ClassNode cls) {
|
||||
if (cls.contains(AFlag.DONT_GENERATE)) {
|
||||
|
||||
@@ -231,11 +231,8 @@ public class SimplifyVisitor extends AbstractVisitor {
|
||||
* Simplify chains of calls to StringBuilder#append() plus constructor of StringBuilder.
|
||||
* Those chains are usually automatically generated by the Java compiler when you create String
|
||||
* concatenations like <code>"text " + 1 + " text"</code>.
|
||||
*
|
||||
* @param mth
|
||||
* @param insn
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings("InnerAssignment") // TODO
|
||||
private static InsnNode convertInvoke(MethodNode mth, InvokeNode insn) {
|
||||
MethodInfo callMth = insn.getCallMth();
|
||||
|
||||
@@ -246,42 +243,42 @@ public class SimplifyVisitor extends AbstractVisitor {
|
||||
&& insn.getArg(0).isInsnWrap()) {
|
||||
try {
|
||||
List<InsnNode> chain = flattenInsnChain(insn);
|
||||
int constrIndex = -1; //RAF
|
||||
int constrIndex = -1; // RAF
|
||||
// Case where new StringBuilder() is called with NO args (the entire
|
||||
// string is created using .append() calls:
|
||||
if (chain.size() > 1 && chain.get(0).getType() == InsnType.CONSTRUCTOR) {
|
||||
constrIndex = 0;
|
||||
} else if (chain.size() > 2 && chain.get(1).getType() == InsnType.CONSTRUCTOR) {
|
||||
//RAF Case where the first string element is String arg to the
|
||||
// RAF Case where the first string element is String arg to the
|
||||
// new StringBuilder("xxx") constructor
|
||||
constrIndex = 1;
|
||||
} else if (chain.size() > 3 && chain.get(2).getType() == InsnType.CONSTRUCTOR) {
|
||||
//RAF Case where the first string element is String.valueOf() arg
|
||||
// RAF Case where the first string element is String.valueOf() arg
|
||||
// to the new StringBuilder(String.valueOf(zzz)) constructor
|
||||
constrIndex = 2;
|
||||
}
|
||||
|
||||
if (constrIndex != -1) { // If we found a CONSTRUCTOR, is it a StringBuilder?
|
||||
if (constrIndex != -1) { // If we found a CONSTRUCTOR, is it a StringBuilder?
|
||||
ConstructorInsn constr = (ConstructorInsn) chain.get(constrIndex);
|
||||
if (constr.getClassType().getFullName().equals(Consts.CLASS_STRING_BUILDER)) {
|
||||
int len = chain.size();
|
||||
int argInd = 1;
|
||||
InsnNode concatInsn = new InsnNode(InsnType.STR_CONCAT, len - 1);
|
||||
InsnNode argInsn;
|
||||
if (constrIndex > 0) { // There was an arg to the StringBuilder constr
|
||||
if (constrIndex > 0) { // There was an arg to the StringBuilder constr
|
||||
InsnWrapArg iwa;
|
||||
if (constrIndex == 2
|
||||
&& (argInsn = chain.get(1)).getType() == InsnType.INVOKE
|
||||
&& ((InvokeNode) argInsn).getCallMth().getName().compareTo("valueOf") == 0) {
|
||||
// The argument of new StringBuilder() is a String.valueOf(chainElement0)
|
||||
iwa = (InsnWrapArg) argInsn.getArg(0);
|
||||
argInd = 3; // Cause for loop below to skip to after the constructor
|
||||
argInd = 3; // Cause for loop below to skip to after the constructor
|
||||
} else {
|
||||
InsnNode firstNode = chain.get(0);
|
||||
if (firstNode instanceof ConstStringNode) {
|
||||
ConstStringNode csn = (ConstStringNode) firstNode;
|
||||
iwa = new InsnWrapArg(csn);
|
||||
argInd = 2; // Cause for loop below to skip to after the constructor
|
||||
argInd = 2; // Cause for loop below to skip to after the constructor
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
@@ -289,7 +286,7 @@ public class SimplifyVisitor extends AbstractVisitor {
|
||||
concatInsn.addArg(iwa);
|
||||
}
|
||||
|
||||
for (; argInd < len; argInd++) { // Add the .append(xxx) arg string to concat
|
||||
for (; argInd < len; argInd++) { // Add the .append(xxx) arg string to concat
|
||||
InsnNode node = chain.get(argInd);
|
||||
MethodInfo method = ((CallMthInterface) node).getCallMth();
|
||||
if (!(node.getArgsCount() < 2 && method.isConstructor() || method.getName().equals("append"))) {
|
||||
|
||||
@@ -30,13 +30,12 @@ public class BlockSplitter extends AbstractVisitor {
|
||||
|
||||
// leave these instructions alone in block node
|
||||
private static final Set<InsnType> SEPARATE_INSNS = EnumSet.of(
|
||||
InsnType.RETURN,
|
||||
InsnType.IF,
|
||||
InsnType.SWITCH,
|
||||
InsnType.MONITOR_ENTER,
|
||||
InsnType.MONITOR_EXIT,
|
||||
InsnType.THROW
|
||||
);
|
||||
InsnType.RETURN,
|
||||
InsnType.IF,
|
||||
InsnType.SWITCH,
|
||||
InsnType.MONITOR_ENTER,
|
||||
InsnType.MONITOR_EXIT,
|
||||
InsnType.THROW);
|
||||
|
||||
public static boolean makeSeparate(InsnType insnType) {
|
||||
return SEPARATE_INSNS.contains(insnType);
|
||||
@@ -88,8 +87,8 @@ public class BlockSplitter extends AbstractVisitor {
|
||||
if (prevInsn != null) {
|
||||
InsnType type = prevInsn.getType();
|
||||
if (type == InsnType.GOTO
|
||||
|| type == InsnType.THROW
|
||||
|| makeSeparate(type)) {
|
||||
|| type == InsnType.THROW
|
||||
|| makeSeparate(type)) {
|
||||
|
||||
if (type == InsnType.RETURN || type == InsnType.THROW) {
|
||||
mth.addExitBlock(curBlock);
|
||||
@@ -102,11 +101,11 @@ public class BlockSplitter extends AbstractVisitor {
|
||||
startNew = true;
|
||||
} else {
|
||||
startNew = isSplitByJump(prevInsn, insn)
|
||||
|| makeSeparate(insn.getType())
|
||||
|| isDoWhile(blocksMap, curBlock, insn)
|
||||
|| insn.contains(AType.EXC_HANDLER)
|
||||
|| prevInsn.contains(AFlag.TRY_LEAVE)
|
||||
|| prevInsn.getType() == InsnType.MOVE_EXCEPTION;
|
||||
|| makeSeparate(insn.getType())
|
||||
|| isDoWhile(blocksMap, curBlock, insn)
|
||||
|| insn.contains(AType.EXC_HANDLER)
|
||||
|| prevInsn.contains(AFlag.TRY_LEAVE)
|
||||
|| prevInsn.getType() == InsnType.MOVE_EXCEPTION;
|
||||
if (startNew) {
|
||||
curBlock = connectNewBlock(mth, curBlock, insn.getOffset());
|
||||
}
|
||||
@@ -154,7 +153,7 @@ public class BlockSplitter extends AbstractVisitor {
|
||||
* For try/catch make empty (splitter) block for connect handlers
|
||||
*/
|
||||
private static BlockNode insertSplitterBlock(MethodNode mth, Map<Integer, BlockNode> blocksMap,
|
||||
BlockNode curBlock, InsnNode insn, boolean startNew) {
|
||||
BlockNode curBlock, InsnNode insn, boolean startNew) {
|
||||
BlockNode splitterBlock;
|
||||
if (insn.getOffset() == 0 || startNew) {
|
||||
splitterBlock = curBlock;
|
||||
@@ -241,7 +240,7 @@ public class BlockSplitter extends AbstractVisitor {
|
||||
}
|
||||
|
||||
private static void connectExceptionHandlers(BlockNode block, InsnNode insn,
|
||||
Map<Integer, BlockNode> blocksMap) {
|
||||
Map<Integer, BlockNode> blocksMap) {
|
||||
CatchAttr catches = insn.get(AType.CATCH_BLOCK);
|
||||
SplitterBlockAttr spl = block.get(AType.SPLITTER_BLOCK);
|
||||
if (catches == null || spl == null) {
|
||||
@@ -329,11 +328,9 @@ public class BlockSplitter extends AbstractVisitor {
|
||||
}
|
||||
|
||||
static boolean removeEmptyDetachedBlocks(MethodNode mth) {
|
||||
return mth.getBasicBlocks().removeIf(block ->
|
||||
block.getInstructions().isEmpty()
|
||||
&& block.getPredecessors().isEmpty()
|
||||
&& block.getSuccessors().isEmpty()
|
||||
);
|
||||
return mth.getBasicBlocks().removeIf(block -> block.getInstructions().isEmpty()
|
||||
&& block.getPredecessors().isEmpty()
|
||||
&& block.getSuccessors().isEmpty());
|
||||
}
|
||||
|
||||
private void removeJumpAttributes(InsnNode[] insnArr) {
|
||||
@@ -357,7 +354,7 @@ public class BlockSplitter extends AbstractVisitor {
|
||||
|
||||
int insnsCount = toRemove.stream().mapToInt(block -> block.getInstructions().size()).sum();
|
||||
mth.addAttr(AType.COMMENTS, "JADX INFO: unreachable blocks removed: " + toRemove.size()
|
||||
+ ", instructions: " + insnsCount);
|
||||
+ ", instructions: " + insnsCount);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.android.dex.Dex.Section;
|
||||
|
||||
import jadx.core.dex.attributes.nodes.SourceFileAttr;
|
||||
import jadx.core.dex.instructions.args.RegisterArg;
|
||||
import jadx.core.dex.nodes.DexNode;
|
||||
|
||||
@@ -105,7 +105,7 @@ public class IfRegionVisitor extends AbstractVisitor {
|
||||
private static void moveReturnToThenBlock(MethodNode mth, IfRegion ifRegion) {
|
||||
if (!mth.getReturnType().equals(ArgType.VOID)
|
||||
&& hasSimpleReturnBlock(ifRegion.getElseRegion())
|
||||
/*&& insnsCount(ifRegion.getThenRegion()) < 2*/) {
|
||||
/* && insnsCount(ifRegion.getThenRegion()) < 2 */) {
|
||||
invertIfRegion(ifRegion);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ import jadx.core.utils.exceptions.JadxOverflowException;
|
||||
@JadxVisitor(
|
||||
name = "LoopRegionVisitor",
|
||||
desc = "Convert 'while' loops to 'for' loops (indexed or for-each)",
|
||||
runBefore = {ProcessVariables.class}
|
||||
runBefore = ProcessVariables.class
|
||||
)
|
||||
public class LoopRegionVisitor extends AbstractVisitor implements IRegionVisitor {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(LoopRegionVisitor.class);
|
||||
@@ -136,7 +136,7 @@ public class LoopRegionVisitor extends AbstractVisitor implements IRegionVisitor
|
||||
}
|
||||
|
||||
private static LoopType checkArrayForEach(MethodNode mth, LoopRegion loopRegion, InsnNode initInsn, InsnNode incrInsn,
|
||||
IfCondition condition) {
|
||||
IfCondition condition) {
|
||||
if (!(incrInsn instanceof ArithNode)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -512,7 +512,7 @@ public class RegionMaker {
|
||||
}
|
||||
|
||||
private static boolean canInsertContinue(BlockNode pred, List<BlockNode> predecessors, BlockNode loopEnd,
|
||||
Set<BlockNode> loopExitNodes) {
|
||||
Set<BlockNode> loopExitNodes) {
|
||||
if (!pred.contains(AFlag.SYNTHETIC)
|
||||
|| BlockUtils.checkLastInsnType(pred, InsnType.CONTINUE)) {
|
||||
return false;
|
||||
@@ -604,7 +604,7 @@ public class RegionMaker {
|
||||
* Traverse from monitor-enter thru successors and collect blocks contains monitor-exit
|
||||
*/
|
||||
private static void traverseMonitorExits(SynchronizedRegion region, InsnArg arg, BlockNode block, Set<BlockNode> exits,
|
||||
Set<BlockNode> visited) {
|
||||
Set<BlockNode> visited) {
|
||||
visited.add(block);
|
||||
for (InsnNode insn : block.getInstructions()) {
|
||||
if (insn.getType() == InsnType.MONITOR_EXIT
|
||||
@@ -881,7 +881,7 @@ public class RegionMaker {
|
||||
}
|
||||
|
||||
private boolean isBadCasesOrder(Map<BlockNode, List<Object>> blocksMap,
|
||||
Map<BlockNode, BlockNode> fallThroughCases) {
|
||||
Map<BlockNode, BlockNode> fallThroughCases) {
|
||||
BlockNode nextCaseBlock = null;
|
||||
for (BlockNode caseBlock : blocksMap.keySet()) {
|
||||
if (nextCaseBlock != null && !caseBlock.equals(nextCaseBlock)) {
|
||||
@@ -893,7 +893,7 @@ public class RegionMaker {
|
||||
}
|
||||
|
||||
private Map<BlockNode, List<Object>> reOrderSwitchCases(Map<BlockNode, List<Object>> blocksMap,
|
||||
Map<BlockNode, BlockNode> fallThroughCases) {
|
||||
Map<BlockNode, BlockNode> fallThroughCases) {
|
||||
List<BlockNode> list = new ArrayList<>(blocksMap.size());
|
||||
list.addAll(blocksMap.keySet());
|
||||
list.sort((a, b) -> {
|
||||
|
||||
+1
-1
@@ -44,7 +44,7 @@ public class ProcessVariables extends AbstractVisitor {
|
||||
return;
|
||||
}
|
||||
checkCodeVars(mth, codeVars);
|
||||
// TODO: reduce code vars by name if debug info applied. Need checks for variable scopes before reduce
|
||||
// TODO: reduce code vars by name if debug info applied (need checks for variable scopes)
|
||||
|
||||
// collect all variables usage
|
||||
CollectUsageRegionVisitor usageCollector = new CollectUsageRegionVisitor();
|
||||
|
||||
@@ -42,9 +42,6 @@ public class UsePlace {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "UsePlace{" +
|
||||
"region=" + region +
|
||||
", block=" + block +
|
||||
'}';
|
||||
return "UsePlace{region=" + region + ", block=" + block + '}';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ import jadx.core.utils.exceptions.JadxRuntimeException;
|
||||
@JadxVisitor(
|
||||
name = "CodeShrinkVisitor",
|
||||
desc = "Inline variables for make code smaller",
|
||||
runAfter = {ModVisitor.class}
|
||||
runAfter = { ModVisitor.class }
|
||||
)
|
||||
public class CodeShrinkVisitor extends AbstractVisitor {
|
||||
|
||||
@@ -63,9 +63,9 @@ public class CodeShrinkVisitor extends AbstractVisitor {
|
||||
ListIterator<RegisterArg> it = args.listIterator(args.size());
|
||||
while (it.hasPrevious()) {
|
||||
RegisterArg arg = it.previous();
|
||||
// if (arg.getName() != null) {
|
||||
// continue;
|
||||
// }
|
||||
// if (arg.getName() != null) {
|
||||
// continue;
|
||||
// }
|
||||
SSAVar sVar = arg.getSVar();
|
||||
// allow inline only one use arg
|
||||
if (sVar == null
|
||||
@@ -122,7 +122,7 @@ public class CodeShrinkVisitor extends AbstractVisitor {
|
||||
}
|
||||
|
||||
private static boolean canMoveBetweenBlocks(InsnNode assignInsn, BlockNode assignBlock,
|
||||
BlockNode useBlock, InsnNode useInsn) {
|
||||
BlockNode useBlock, InsnNode useInsn) {
|
||||
if (!BlockUtils.isPathExists(assignBlock, useBlock)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -20,8 +20,7 @@ final class RenameState {
|
||||
mth,
|
||||
mth.getEnterBlock(),
|
||||
new SSAVar[regsCount],
|
||||
new int[regsCount]
|
||||
);
|
||||
new int[regsCount]);
|
||||
for (RegisterArg arg : mth.getArguments(true)) {
|
||||
SSAVar ssaVar = state.startVar(arg);
|
||||
ssaVar.add(AFlag.METHOD_ARGUMENT);
|
||||
@@ -34,8 +33,7 @@ final class RenameState {
|
||||
state.mth,
|
||||
block,
|
||||
Arrays.copyOf(state.vars, state.vars.length),
|
||||
state.versions
|
||||
);
|
||||
state.versions);
|
||||
}
|
||||
|
||||
private RenameState(MethodNode mth, BlockNode block, SSAVar[] vars, int[] versions) {
|
||||
|
||||
@@ -213,7 +213,7 @@ public class SSATransform extends AbstractVisitor {
|
||||
if (parentInsn != null
|
||||
&& parentInsn.getResult() != null
|
||||
&& parentInsn.contains(AFlag.TRY_LEAVE)
|
||||
&& phi.removeArg(arg) /* TODO: fix registers removing*/) {
|
||||
&& phi.removeArg(arg) /* TODO: fix registers removing */) {
|
||||
argsCount--;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ public final class TypeBoundConst implements ITypeBound {
|
||||
private final ArgType type;
|
||||
private final RegisterArg arg;
|
||||
|
||||
|
||||
public TypeBoundConst(BoundEnum bound, ArgType type) {
|
||||
this(bound, type, null);
|
||||
}
|
||||
@@ -45,8 +44,7 @@ public final class TypeBoundConst implements ITypeBound {
|
||||
return false;
|
||||
}
|
||||
TypeBoundConst that = (TypeBoundConst) o;
|
||||
return bound == that.bound &&
|
||||
Objects.equals(type, that.type);
|
||||
return bound == that.bound && Objects.equals(type, that.type);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -59,7 +59,7 @@ public class TypeCompare {
|
||||
// both arrays
|
||||
return compareTypes(first.getArrayElement(), second.getArrayElement());
|
||||
}
|
||||
if (!firstKnown /*&& !secondKnown*/) {
|
||||
if (!firstKnown /* && !secondKnown */) {
|
||||
int variantLen = Integer.compare(first.getPossibleTypes().length, second.getPossibleTypes().length);
|
||||
return variantLen > 0 ? WIDER : NARROW;
|
||||
}
|
||||
@@ -188,7 +188,7 @@ public class TypeCompare {
|
||||
return NARROW_BY_GENERIC;
|
||||
}
|
||||
// TODO: fill extendTypes
|
||||
// return CONFLICT;
|
||||
// return CONFLICT;
|
||||
return NARROW_BY_GENERIC;
|
||||
}
|
||||
|
||||
|
||||
+37
-37
@@ -42,12 +42,12 @@ import jadx.core.utils.BlockUtils;
|
||||
import jadx.core.utils.Utils;
|
||||
|
||||
@JadxVisitor(
|
||||
name = "Type Inference",
|
||||
desc = "Calculate best types for SSA variables",
|
||||
runAfter = {
|
||||
SSATransform.class,
|
||||
ConstInlineVisitor.class
|
||||
}
|
||||
name = "Type Inference",
|
||||
desc = "Calculate best types for SSA variables",
|
||||
runAfter = {
|
||||
SSATransform.class,
|
||||
ConstInlineVisitor.class
|
||||
}
|
||||
)
|
||||
public final class TypeInferenceVisitor extends AbstractVisitor {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(TypeInferenceVisitor.class);
|
||||
@@ -77,8 +77,8 @@ public final class TypeInferenceVisitor extends AbstractVisitor {
|
||||
for (SSAVar var : mth.getSVars()) {
|
||||
ArgType type = var.getTypeInfo().getType();
|
||||
if (!type.isTypeKnown()
|
||||
&& !var.getAssign().isTypeImmutable()
|
||||
&& !tryDeduceType(mth, var, type)) {
|
||||
&& !var.getAssign().isTypeImmutable()
|
||||
&& !tryDeduceType(mth, var, type)) {
|
||||
resolved = false;
|
||||
}
|
||||
}
|
||||
@@ -180,9 +180,9 @@ public final class TypeInferenceVisitor extends AbstractVisitor {
|
||||
|
||||
private Optional<ArgType> selectBestTypeFromBounds(Set<ITypeBound> bounds) {
|
||||
return bounds.stream()
|
||||
.map(ITypeBound::getType)
|
||||
.filter(Objects::nonNull)
|
||||
.max(typeUpdate.getArgTypeComparator());
|
||||
.map(ITypeBound::getType)
|
||||
.filter(Objects::nonNull)
|
||||
.max(typeUpdate.getArgTypeComparator());
|
||||
}
|
||||
|
||||
private void attachBounds(SSAVar var) {
|
||||
@@ -383,36 +383,36 @@ public final class TypeInferenceVisitor extends AbstractVisitor {
|
||||
|
||||
private void processIncompatiblePrimitives(MethodNode mth, SSAVar var) {
|
||||
if (var.getAssign().getType() == ArgType.BOOLEAN) {
|
||||
for (ITypeBound bound : var.getTypeInfo().getBounds()) {
|
||||
if (bound.getBound() == BoundEnum.USE
|
||||
&& bound.getType().isPrimitive() && bound.getType() != ArgType.BOOLEAN) {
|
||||
InsnNode insn = bound.getArg().getParentInsn();
|
||||
if (insn.getType() == InsnType.CAST) {
|
||||
continue;
|
||||
};
|
||||
for (ITypeBound bound : var.getTypeInfo().getBounds()) {
|
||||
if (bound.getBound() == BoundEnum.USE
|
||||
&& bound.getType().isPrimitive() && bound.getType() != ArgType.BOOLEAN) {
|
||||
InsnNode insn = bound.getArg().getParentInsn();
|
||||
if (insn.getType() == InsnType.CAST) {
|
||||
continue;
|
||||
}
|
||||
|
||||
IndexInsnNode castNode = new IndexInsnNode(InsnType.CAST, bound.getType(), 1);
|
||||
castNode.addArg(bound.getArg());
|
||||
castNode.setResult(InsnArg.reg(bound.getArg().getRegNum(), bound.getType()));
|
||||
IndexInsnNode castNode = new IndexInsnNode(InsnType.CAST, bound.getType(), 1);
|
||||
castNode.addArg(bound.getArg());
|
||||
castNode.setResult(InsnArg.reg(bound.getArg().getRegNum(), bound.getType()));
|
||||
|
||||
SSAVar newVar = mth.makeNewSVar(castNode.getResult().getRegNum(), castNode.getResult());
|
||||
CodeVar codeVar = new CodeVar();
|
||||
codeVar.setType(bound.getType());
|
||||
newVar.setCodeVar(codeVar);
|
||||
newVar.getTypeInfo().setType(bound.getType());
|
||||
SSAVar newVar = mth.makeNewSVar(castNode.getResult().getRegNum(), castNode.getResult());
|
||||
CodeVar codeVar = new CodeVar();
|
||||
codeVar.setType(bound.getType());
|
||||
newVar.setCodeVar(codeVar);
|
||||
newVar.getTypeInfo().setType(bound.getType());
|
||||
|
||||
for (int i = insn.getArgsCount() - 1; i >= 0; i--) {
|
||||
if (insn.getArg(i) == bound.getArg()) {
|
||||
insn.setArg(i, castNode.getResult().duplicate());
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (int i = insn.getArgsCount() - 1; i >= 0; i--) {
|
||||
if (insn.getArg(i) == bound.getArg()) {
|
||||
insn.setArg(i, castNode.getResult().duplicate());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
BlockNode blockNode = BlockUtils.getBlockByInsn(mth, insn);
|
||||
List<InsnNode> insnList = blockNode.getInstructions();
|
||||
insnList.add(insnList.indexOf(insn), castNode);
|
||||
}
|
||||
}
|
||||
BlockNode blockNode = BlockUtils.getBlockByInsn(mth, insn);
|
||||
List<InsnNode> insnList = blockNode.getInstructions();
|
||||
insnList.add(insnList.indexOf(insn), castNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,9 +27,6 @@ public class TypeInfo {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TypeInfo{" +
|
||||
"type=" + type +
|
||||
", bounds=" + bounds +
|
||||
'}';
|
||||
return "TypeInfo{type=" + type + ", bounds=" + bounds + '}';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ public final class TypeUpdate {
|
||||
if (candidateType == null) {
|
||||
return REJECT;
|
||||
}
|
||||
if (!candidateType.isTypeKnown()/* && ssaVar.getTypeInfo().getType().isTypeKnown()*/) {
|
||||
if (!candidateType.isTypeKnown()/* && ssaVar.getTypeInfo().getType().isTypeKnown() */) {
|
||||
return REJECT;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,8 +23,7 @@ public class ExportGradleProject {
|
||||
|
||||
private static final Set<String> IGNORE_CLS_NAMES = new HashSet<>(Arrays.asList(
|
||||
"R",
|
||||
"BuildConfig"
|
||||
));
|
||||
"BuildConfig"));
|
||||
|
||||
private final RootNode root;
|
||||
private final File outDir;
|
||||
|
||||
@@ -22,7 +22,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
public final class ImmutableList<E> implements List<E>, RandomAccess {
|
||||
private final E[] arr;
|
||||
|
||||
@SuppressWarnings({"unchecked", "SuspiciousArrayCast"})
|
||||
@SuppressWarnings({ "unchecked", "SuspiciousArrayCast" })
|
||||
public ImmutableList(Collection<E> col) {
|
||||
this((E[]) Objects.requireNonNull(col).toArray());
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ public final class InsnList implements Iterable<InsnNode> {
|
||||
}
|
||||
|
||||
public static void remove(List<InsnNode> list, InsnNode insn) {
|
||||
for (Iterator<InsnNode> iterator = list.iterator(); iterator.hasNext(); ) {
|
||||
for (Iterator<InsnNode> iterator = list.iterator(); iterator.hasNext();) {
|
||||
InsnNode next = iterator.next();
|
||||
if (next == insn) {
|
||||
iterator.remove();
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
package jadx.core.utils;
|
||||
|
||||
import com.android.dx.io.instructions.DecodedInstruction;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.android.dx.io.instructions.DecodedInstruction;
|
||||
|
||||
import jadx.core.dex.attributes.AType;
|
||||
import jadx.core.dex.info.FieldInfo;
|
||||
import jadx.core.dex.instructions.ConstClassNode;
|
||||
|
||||
@@ -5,12 +5,13 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import com.android.dx.rop.code.AccessFlags;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.android.dx.rop.code.AccessFlags;
|
||||
|
||||
import jadx.core.codegen.ClassGen;
|
||||
import jadx.core.codegen.CodeWriter;
|
||||
import jadx.core.deobf.NameMapper;
|
||||
@@ -103,8 +104,7 @@ public class AndroidResourcesUtils {
|
||||
final String resTypeName = resource.getTypeName();
|
||||
ClassNode typeCls = innerClsMap.computeIfAbsent(
|
||||
resTypeName,
|
||||
name -> addClassForResType(resCls, rClsExists, name)
|
||||
);
|
||||
name -> addClassForResType(resCls, rClsExists, name));
|
||||
final String resName;
|
||||
if ("style".equals(resTypeName)) {
|
||||
resName = resource.getKeyName().replace('.', '_');
|
||||
|
||||
@@ -81,6 +81,7 @@ public class ExtDataInput extends DataInputDelegate {
|
||||
* requested (this is similar to DataInputStream's wrapper).
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("InnerAssignment")
|
||||
public final int skipBytes(int n) throws IOException {
|
||||
int total = 0;
|
||||
int cur = 0;
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package jadx.core.utils.android;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.DataInput;
|
||||
@@ -24,6 +23,8 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
import jadx.core.utils.exceptions.JadxException;
|
||||
@@ -110,7 +111,7 @@ public class Res9patchStreamDecoder {
|
||||
public final int[] yDivs;
|
||||
|
||||
public NinePatch(int padLeft, int padRight, int padTop, int padBottom,
|
||||
int[] xDivs, int[] yDivs) {
|
||||
int[] xDivs, int[] yDivs) {
|
||||
this.padLeft = padLeft;
|
||||
this.padRight = padRight;
|
||||
this.padTop = padTop;
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
package jadx.core.utils.files;
|
||||
|
||||
import static jadx.core.utils.files.FileUtils.isApkFile;
|
||||
import static jadx.core.utils.files.FileUtils.isZipDexFile;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@@ -31,6 +28,9 @@ import jadx.core.utils.exceptions.DecodeException;
|
||||
import jadx.core.utils.exceptions.JadxException;
|
||||
import jadx.core.utils.exceptions.JadxRuntimeException;
|
||||
|
||||
import static jadx.core.utils.files.FileUtils.isApkFile;
|
||||
import static jadx.core.utils.files.FileUtils.isZipDexFile;
|
||||
|
||||
public class InputFile {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(InputFile.class);
|
||||
|
||||
@@ -117,7 +117,7 @@ public class InputFile {
|
||||
// we should consider the input file could contain only one single dex, multi-dex,
|
||||
// or instantRun support dex for Android .apk files
|
||||
String instantRunDexSuffix = "classes" + ext;
|
||||
for (Enumeration<? extends ZipEntry> e = zf.entries(); e.hasMoreElements(); ) {
|
||||
for (Enumeration<? extends ZipEntry> e = zf.entries(); e.hasMoreElements();) {
|
||||
ZipEntry entry = e.nextElement();
|
||||
if (!ZipSecurity.isValidZipEntry(entry)) {
|
||||
continue;
|
||||
|
||||
@@ -39,27 +39,27 @@ public class JavaToDex {
|
||||
|
||||
public List<Path> convert(Path jar) throws JadxException {
|
||||
try (ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
ByteArrayOutputStream errOut = new ByteArrayOutputStream()) {
|
||||
ByteArrayOutputStream errOut = new ByteArrayOutputStream()) {
|
||||
DxContext context = new DxContext(out, errOut);
|
||||
Path dir = Files.createTempDirectory("jadx");
|
||||
DxArgs args = new DxArgs(
|
||||
context,
|
||||
dir.toAbsolutePath().toString(),
|
||||
new String[]{jar.toAbsolutePath().toString()});
|
||||
new String[] { jar.toAbsolutePath().toString() });
|
||||
int result = new Main(context).runDx(args);
|
||||
dxErrors = errOut.toString(CHARSET_NAME);
|
||||
if (result != 0) {
|
||||
throw new JadxException("Java to dex conversion error, code: " + result);
|
||||
}
|
||||
List<Path> list = new ArrayList<>();
|
||||
try (DirectoryStream<Path> ds = Files.newDirectoryStream(dir)) {
|
||||
for (Path child : ds) {
|
||||
list.add(child);
|
||||
child.toFile().deleteOnExit();
|
||||
}
|
||||
}
|
||||
dir.toFile().deleteOnExit();
|
||||
return list;
|
||||
try (DirectoryStream<Path> ds = Files.newDirectoryStream(dir)) {
|
||||
for (Path child : ds) {
|
||||
list.add(child);
|
||||
child.toFile().deleteOnExit();
|
||||
}
|
||||
}
|
||||
dir.toFile().deleteOnExit();
|
||||
return list;
|
||||
} catch (Exception e) {
|
||||
throw new JadxException("dx exception: " + e.getMessage(), e);
|
||||
}
|
||||
|
||||
@@ -13,7 +13,8 @@ public class ZipSecurity {
|
||||
// size of uncompressed zip entry shouldn't be bigger of compressed in MAX_SIZE_DIFF times
|
||||
private static final int MAX_SIZE_DIFF = 100;
|
||||
|
||||
private ZipSecurity() {}
|
||||
private ZipSecurity() {
|
||||
}
|
||||
|
||||
private static boolean isInSubDirectoryInternal(File baseDir, File canonFile) {
|
||||
if (canonFile == null) {
|
||||
|
||||
@@ -20,16 +20,17 @@ import jadx.core.utils.StringUtils;
|
||||
import jadx.core.utils.exceptions.JadxRuntimeException;
|
||||
import jadx.core.xmlgen.entry.ValuesParser;
|
||||
|
||||
/* TODO:
|
||||
Don't die when error occurs
|
||||
Check error cases, maybe checked const values are not always the same
|
||||
Better error messages
|
||||
What to do, when Binary XML Manifest is > size(int)?
|
||||
Check for missing chunk size types
|
||||
Implement missing data types
|
||||
Use line numbers to recreate EXACT AndroidManifest
|
||||
Check Element chunk size
|
||||
*/
|
||||
/*
|
||||
* TODO:
|
||||
* Don't die when error occurs
|
||||
* Check error cases, maybe checked const values are not always the same
|
||||
* Better error messages
|
||||
* What to do, when Binary XML Manifest is > size(int)?
|
||||
* Check for missing chunk size types
|
||||
* Implement missing data types
|
||||
* Use line numbers to recreate EXACT AndroidManifest
|
||||
* Check Element chunk size
|
||||
*/
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class BinaryXMLParser extends CommonBinaryParser {
|
||||
@@ -74,8 +75,8 @@ public class BinaryXMLParser extends CommonBinaryParser {
|
||||
for (Field f : rStyleCls.getFields()) {
|
||||
styleMap.put(f.getInt(f.getType()), f.getName());
|
||||
}
|
||||
} catch (Exception th) {
|
||||
LOG.error("Android R class loading failed", th);
|
||||
} catch (Exception e) {
|
||||
LOG.error("Android R class loading failed", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -330,7 +331,7 @@ public class BinaryXMLParser extends CommonBinaryParser {
|
||||
}
|
||||
|
||||
private String generateNameForNS(String attrUrl) {
|
||||
for (int i = 1; ; i++) {
|
||||
for (int i = 1;; i++) {
|
||||
String attrName = "ns" + i;
|
||||
if (!nsMap.containsValue(attrName) && !nsMapGenerated.contains(attrName)) {
|
||||
nsMapGenerated.add(attrName);
|
||||
@@ -369,7 +370,7 @@ public class BinaryXMLParser extends CommonBinaryParser {
|
||||
}
|
||||
|
||||
private void decodeAttribute(int attributeNS, int attrValDataType, int attrValData,
|
||||
String shortNsName, String attrName) {
|
||||
String shortNsName, String attrName) {
|
||||
if (attrValDataType == TYPE_REFERENCE) {
|
||||
// reference custom processing
|
||||
String name = styleMap.get(attrValData);
|
||||
@@ -422,9 +423,9 @@ public class BinaryXMLParser extends CommonBinaryParser {
|
||||
} else {
|
||||
writer.startLine("</");
|
||||
writer.attachSourceLine(endLineNumber);
|
||||
// if (elementNS != -1) {
|
||||
// writer.add(getString(elementNS)).add(':');
|
||||
// }
|
||||
// if (elementNS != -1) {
|
||||
// writer.add(getString(elementNS)).add(':');
|
||||
// }
|
||||
writer.add(elemName).add('>');
|
||||
}
|
||||
isLastEnd = true;
|
||||
@@ -443,8 +444,7 @@ public class BinaryXMLParser extends CommonBinaryParser {
|
||||
String generated;
|
||||
do {
|
||||
generated = generateTagAttrName();
|
||||
}
|
||||
while (tagAttrDeobfNames.containsValue(generated));
|
||||
} while (tagAttrDeobfNames.containsValue(generated));
|
||||
tagAttrDeobfNames.put(originalName, generated);
|
||||
return generated;
|
||||
}
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
package jadx.core.xmlgen;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import java.io.InputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.w3c.dom.Document;
|
||||
|
||||
@@ -71,7 +71,7 @@ public class ParserConstants {
|
||||
// ...end of integer flavors.
|
||||
protected static final int TYPE_LAST_INT = 0x1f;
|
||||
|
||||
// Where the unit type information is. This gives us 16 possible
|
||||
// Where the unit type information is. This gives us 16 possible
|
||||
// types, as defined below.
|
||||
protected static final int COMPLEX_UNIT_SHIFT = 0;
|
||||
protected static final int COMPLEX_UNIT_MASK = 0xf;
|
||||
@@ -95,7 +95,7 @@ public class ParserConstants {
|
||||
protected static final int COMPLEX_UNIT_FRACTION_PARENT = 1;
|
||||
|
||||
// Where the radix information is, telling where the decimal place
|
||||
// appears in the mantissa. This give us 4 possible fixed point
|
||||
// appears in the mantissa. This give us 4 possible fixed point
|
||||
// representations as defined below.
|
||||
protected static final int COMPLEX_RADIX_SHIFT = 4;
|
||||
protected static final int COMPLEX_RADIX_MASK = 0x3;
|
||||
@@ -109,13 +109,13 @@ public class ParserConstants {
|
||||
// The mantissa magnitude is 0 bits -- i.e, 0x0.nnnnnn
|
||||
protected static final int COMPLEX_RADIX_0P23 = 3;
|
||||
|
||||
// Where the actual value is. This gives us 23 bits of
|
||||
// precision. The top bit is the sign.
|
||||
// Where the actual value is. This gives us 23 bits of
|
||||
// precision. The top bit is the sign.
|
||||
protected static final int COMPLEX_MANTISSA_SHIFT = 8;
|
||||
protected static final int COMPLEX_MANTISSA_MASK = 0xffffff;
|
||||
|
||||
protected static final double MANTISSA_MULT = 1.0f / (1 << COMPLEX_MANTISSA_SHIFT);
|
||||
protected static final double[] RADIX_MULTS = new double[]{
|
||||
protected static final double[] RADIX_MULTS = new double[] {
|
||||
1.0f * MANTISSA_MULT,
|
||||
1.0f / (1 << 7) * MANTISSA_MULT,
|
||||
1.0f / (1 << 15) * MANTISSA_MULT,
|
||||
@@ -187,7 +187,7 @@ public class ParserConstants {
|
||||
protected static final int ATTR_TYPE_REFERENCE = 1;
|
||||
// Attribute holds a generic string.
|
||||
protected static final int ATTR_TYPE_STRING = 1 << 1;
|
||||
// Attribute holds an integer value. ATTR_MIN and ATTR_MIN can
|
||||
// Attribute holds an integer value. ATTR_MIN and ATTR_MIN can
|
||||
// optionally specify a constrained range of possible integer values.
|
||||
protected static final int ATTR_TYPE_INTEGER = 1 << 2;
|
||||
// Attribute holds a boolean integer.
|
||||
@@ -200,10 +200,10 @@ public class ParserConstants {
|
||||
protected static final int ATTR_TYPE_DIMENSION = 1 << 6;
|
||||
// Attribute holds a fraction value, such as "20%".
|
||||
protected static final int ATTR_TYPE_FRACTION = 1 << 7;
|
||||
// Attribute holds an enumeration. The enumeration values are
|
||||
// Attribute holds an enumeration. The enumeration values are
|
||||
// supplied as additional entries in the map.
|
||||
protected static final int ATTR_TYPE_ENUM = 1 << 16;
|
||||
// Attribute holds a bitmaks of flags. The flag bit values are
|
||||
// Attribute holds a bitmaks of flags. The flag bit values are
|
||||
// supplied as additional entries in the map.
|
||||
protected static final int ATTR_TYPE_FLAGS = 1 << 17;
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ public class ResTableParser extends CommonBinaryParser {
|
||||
for (ResourceEntry ri : resStorage.getResources()) {
|
||||
if (addedValues.add(ri.getTypeName() + '.' + ri.getKeyName())) {
|
||||
String format = String.format("<public type=\"%s\" name=\"%s\" id=\"%s\" />",
|
||||
ri.getTypeName(), ri.getKeyName(), ri.getId());
|
||||
ri.getTypeName(), ri.getKeyName(), ri.getId());
|
||||
writer.startLine(format);
|
||||
}
|
||||
}
|
||||
@@ -101,7 +101,7 @@ public class ResTableParser extends CommonBinaryParser {
|
||||
void decodeTableChunk() throws IOException {
|
||||
is.checkInt16(RES_TABLE_TYPE, "Not a table chunk");
|
||||
is.checkInt16(0x000c, "Unexpected table header size");
|
||||
/*int size = */
|
||||
/* int size = */
|
||||
is.readInt32();
|
||||
int pkgCount = is.readInt32();
|
||||
|
||||
@@ -167,7 +167,7 @@ public class ResTableParser extends CommonBinaryParser {
|
||||
@SuppressWarnings("unused")
|
||||
private void parseTypeSpecChunk() throws IOException {
|
||||
is.checkInt16(0x0010, "Unexpected type spec header size");
|
||||
/*int size = */
|
||||
/* int size = */
|
||||
is.readInt32();
|
||||
|
||||
int id = is.readInt8();
|
||||
@@ -179,9 +179,9 @@ public class ResTableParser extends CommonBinaryParser {
|
||||
}
|
||||
|
||||
private void parseTypeChunk(long start, PackageChunk pkg) throws IOException {
|
||||
/*int headerSize = */
|
||||
/* int headerSize = */
|
||||
is.readInt16();
|
||||
/*int size = */
|
||||
/* int size = */
|
||||
is.readInt32();
|
||||
|
||||
int id = is.readInt8();
|
||||
@@ -221,7 +221,7 @@ public class ResTableParser extends CommonBinaryParser {
|
||||
int resRef = pkg.getId() << 24 | typeId << 16 | entryId;
|
||||
String typeName = pkg.getTypeStrings()[typeId - 1];
|
||||
String keyName = pkg.getKeyStrings()[key];
|
||||
if(keyName.isEmpty()) {
|
||||
if (keyName.isEmpty()) {
|
||||
keyName = "RES_" + resRef; // autogenerate key name
|
||||
}
|
||||
ResourceEntry ri = new ResourceEntry(resRef, pkg.getName(), typeName, keyName);
|
||||
@@ -317,11 +317,11 @@ public class ResTableParser extends CommonBinaryParser {
|
||||
is.skipToPos(start + size, "Config skip trailing bytes");
|
||||
|
||||
return new EntryConfig(mcc, mnc, language, country,
|
||||
orientation, touchscreen, density, keyboard, navigation,
|
||||
inputFlags, screenWidth, screenHeight, sdkVersion,
|
||||
screenLayout, uiMode, smallestScreenWidthDp, screenWidthDp,
|
||||
screenHeightDp, localeScript, localeVariant, screenLayout2,
|
||||
colorMode, false, size);
|
||||
orientation, touchscreen, density, keyboard, navigation,
|
||||
inputFlags, screenWidth, screenHeight, sdkVersion,
|
||||
screenLayout, uiMode, smallestScreenWidthDp, screenWidthDp,
|
||||
screenHeightDp, localeScript, localeVariant, screenLayout2,
|
||||
colorMode, false, size);
|
||||
}
|
||||
|
||||
private char[] unpackLocaleOrRegion(byte in0, byte in1, char base) {
|
||||
@@ -333,9 +333,9 @@ public class ResTableParser extends CommonBinaryParser {
|
||||
|
||||
// since this function handles languages & regions, we add the value(s) to the base char
|
||||
// which is usually 'a' or '0' depending on language or region.
|
||||
return new char[]{(char) (first + base), (char) (second + base), (char) (third + base)};
|
||||
return new char[] { (char) (first + base), (char) (second + base), (char) (third + base) };
|
||||
}
|
||||
return new char[]{(char) in0, (char) in1};
|
||||
return new char[] { (char) in0, (char) in1 };
|
||||
}
|
||||
|
||||
private String readScriptOrVariantChar(int length) throws IOException {
|
||||
|
||||
@@ -22,8 +22,7 @@ public class ResXmlGen {
|
||||
private static final Set<String> SKIP_RES_TYPES = new HashSet<>(Arrays.asList(
|
||||
"layout",
|
||||
"mipmap",
|
||||
"id"
|
||||
));
|
||||
"id"));
|
||||
|
||||
private final ResourceStorage resStorage;
|
||||
private final ValuesParser vp;
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@@ -37,7 +35,7 @@ import java.util.Arrays;
|
||||
* @author Glenn Marcy, IBM
|
||||
* @author Andy Clark, IBM
|
||||
* @author Eric Ye, IBM
|
||||
* @author Arnaud Le Hors, IBM
|
||||
* @author Arnaud Le Hors, IBM
|
||||
* @author Michael Glavassevich, IBM
|
||||
* @author Rahul Srivastava, Sun Microsystems Inc.
|
||||
* @version $Id: XMLChar.java 674378 2008-07-07 00:52:45Z mrglavas $
|
||||
@@ -799,8 +797,8 @@ public class XMLChar {
|
||||
* @param c The character to check.
|
||||
*/
|
||||
public static boolean isValid(int c) {
|
||||
return (c < 0x10000 && (CHARS[c] & MASK_VALID) != 0) ||
|
||||
(0x10000 <= c && c <= 0x10FFFF);
|
||||
return (c < 0x10000 && (CHARS[c] & MASK_VALID) != 0)
|
||||
|| (0x10000 <= c && c <= 0x10FFFF);
|
||||
} // isValid(int):boolean
|
||||
|
||||
/**
|
||||
@@ -818,8 +816,8 @@ public class XMLChar {
|
||||
* @param c The character to check.
|
||||
*/
|
||||
public static boolean isContent(int c) {
|
||||
return (c < 0x10000 && (CHARS[c] & MASK_CONTENT) != 0) ||
|
||||
(0x10000 <= c && c <= 0x10FFFF);
|
||||
return (c < 0x10000 && (CHARS[c] & MASK_CONTENT) != 0)
|
||||
|| (0x10000 <= c && c <= 0x10FFFF);
|
||||
} // isContent(int):boolean
|
||||
|
||||
/**
|
||||
@@ -999,9 +997,9 @@ public class XMLChar {
|
||||
if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) {
|
||||
for (int i = 1; i < length; i++) {
|
||||
c = ianaEncoding.charAt(i);
|
||||
if ((c < 'A' || c > 'Z') && (c < 'a' || c > 'z') &&
|
||||
(c < '0' || c > '9') && c != '.' && c != '_' &&
|
||||
c != '-') {
|
||||
if ((c < 'A' || c > 'Z') && (c < 'a' || c > 'z')
|
||||
&& (c < '0' || c > '9') && c != '.' && c != '_'
|
||||
&& c != '-') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1026,9 +1024,9 @@ public class XMLChar {
|
||||
if (length > 0) {
|
||||
for (int i = 1; i < length; i++) {
|
||||
char c = javaEncoding.charAt(i);
|
||||
if ((c < 'A' || c > 'Z') && (c < 'a' || c > 'z') &&
|
||||
(c < '0' || c > '9') && c != '.' && c != '_' &&
|
||||
c != '-') {
|
||||
if ((c < 'A' || c > 'Z') && (c < 'a' || c > 'z')
|
||||
&& (c < '0' || c > '9') && c != '.' && c != '_'
|
||||
&& c != '-') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1046,7 +1044,7 @@ public class XMLChar {
|
||||
*
|
||||
* @param value the string to be trimmed
|
||||
* @return the given string with the space characters trimmed
|
||||
* from both ends
|
||||
* from both ends
|
||||
*/
|
||||
public static String trim(String value) {
|
||||
int start;
|
||||
|
||||
@@ -11,12 +11,13 @@ import jadx.core.dex.nodes.RootNode;
|
||||
* but were changed during deobfuscation
|
||||
*/
|
||||
public class XmlDeobf {
|
||||
private static final Map<String, String> deobfMap = new HashMap<>();
|
||||
private static final Map<String, String> DEOBF_MAP = new HashMap<>();
|
||||
|
||||
private XmlDeobf() {}
|
||||
private XmlDeobf() {
|
||||
}
|
||||
|
||||
public static String deobfClassName(RootNode rootNode, String potencialClassName,
|
||||
String packageName) {
|
||||
String packageName) {
|
||||
|
||||
if (packageName != null && potencialClassName.startsWith(".")) {
|
||||
potencialClassName = packageName + potencialClassName;
|
||||
@@ -25,17 +26,17 @@ public class XmlDeobf {
|
||||
}
|
||||
|
||||
private static String getNewClassName(RootNode rootNode, String old) {
|
||||
if (deobfMap.isEmpty()) {
|
||||
if (DEOBF_MAP.isEmpty()) {
|
||||
for (ClassNode classNode : rootNode.getClasses(true)) {
|
||||
if (classNode.getAlias() != null) {
|
||||
String oldName = classNode.getClassInfo().getFullName();
|
||||
String newName = classNode.getAlias().getFullName();
|
||||
if (!oldName.equals(newName)) {
|
||||
deobfMap.put(oldName, newName);
|
||||
DEOBF_MAP.put(oldName, newName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return deobfMap.get(old);
|
||||
return DEOBF_MAP.get(old);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,8 @@ public class XmlSecurity {
|
||||
|
||||
private static DocumentBuilderFactory secureDbf = null;
|
||||
|
||||
private XmlSecurity() {}
|
||||
private XmlSecurity() {
|
||||
}
|
||||
|
||||
public static DocumentBuilderFactory getSecureDbf() throws ParserConfigurationException {
|
||||
synchronized (XmlSecurity.class) {
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package jadx.core.xmlgen.entry;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
@@ -21,7 +22,8 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Original source code can be found
|
||||
* <a href="https://raw.githubusercontent.com/iBotPeaches/Apktool/master/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/ResConfigFlags.java">here</a>
|
||||
* <a href=
|
||||
* "https://raw.githubusercontent.com/iBotPeaches/Apktool/master/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/data/ResConfigFlags.java">here</a>
|
||||
*/
|
||||
|
||||
public class EntryConfig {
|
||||
@@ -64,13 +66,13 @@ public class EntryConfig {
|
||||
private final int size;
|
||||
|
||||
public EntryConfig(short mcc, short mnc, char[] language,
|
||||
char[] region, byte orientation,
|
||||
byte touchscreen, int density, byte keyboard, byte navigation,
|
||||
byte inputFlags, short screenWidth, short screenHeight,
|
||||
short sdkVersion, byte screenLayout, byte uiMode,
|
||||
short smallestScreenWidthDp, short screenWidthDp,
|
||||
short screenHeightDp, char[] localeScript, char[] localeVariant,
|
||||
byte screenLayout2, byte colorMode, boolean isInvalid, int size) {
|
||||
char[] region, byte orientation,
|
||||
byte touchscreen, int density, byte keyboard, byte navigation,
|
||||
byte inputFlags, short screenWidth, short screenHeight,
|
||||
short sdkVersion, byte screenLayout, byte uiMode,
|
||||
short smallestScreenWidthDp, short screenWidthDp,
|
||||
short screenHeightDp, char[] localeScript, char[] localeVariant,
|
||||
byte screenLayout2, byte colorMode, boolean isInvalid, int size) {
|
||||
if (orientation < 0 || orientation > 3) {
|
||||
LOG.warn("Invalid orientation value: {}", orientation);
|
||||
orientation = 0;
|
||||
@@ -394,7 +396,8 @@ public class EntryConfig {
|
||||
}
|
||||
|
||||
private short getNaturalSdkVersionRequirement() {
|
||||
if ((uiMode & MASK_UI_MODE_TYPE) == UI_MODE_TYPE_VR_HEADSET || (colorMode & COLOR_WIDE_MASK) != 0 || ((colorMode & COLOR_HDR_MASK) != 0)) {
|
||||
if ((uiMode & MASK_UI_MODE_TYPE) == UI_MODE_TYPE_VR_HEADSET || (colorMode & COLOR_WIDE_MASK) != 0
|
||||
|| ((colorMode & COLOR_HDR_MASK) != 0)) {
|
||||
return SDK_OREO;
|
||||
}
|
||||
if ((screenLayout2 & MASK_SCREENROUND) != 0) {
|
||||
@@ -421,8 +424,8 @@ public class EntryConfig {
|
||||
// check for old style non BCP47 tags
|
||||
// allows values-xx-rXX, values-xx, values-xxx-rXX
|
||||
// denies values-xxx, anything else
|
||||
if (localeVariant == null && localeScript == null && (region[0] != '\00' || language[0] != '\00') &&
|
||||
region.length != 3) {
|
||||
if (localeVariant == null && localeScript == null && (region[0] != '\00' || language[0] != '\00')
|
||||
&& region.length != 3) {
|
||||
sb.append('-').append(language);
|
||||
if (region[0] != '\00') {
|
||||
sb.append("-r").append(region);
|
||||
|
||||
@@ -8,10 +8,13 @@ import java.lang.annotation.Target;
|
||||
/**
|
||||
* Indicates a test which is known to fail.
|
||||
*
|
||||
* <p>This would cause a failure to be considered as success and a success as failure,
|
||||
* with the benefit of updating the related issue when it has been resolved even unintentionally.</p>
|
||||
* <p>
|
||||
* This would cause a failure to be considered as success and a success as failure,
|
||||
* with the benefit of updating the related issue when it has been resolved even unintentionally.
|
||||
* </p>
|
||||
*
|
||||
* <p>To have an effect, the test class must be annotated with:
|
||||
* <p>
|
||||
* To have an effect, the test class must be annotated with:
|
||||
*
|
||||
* <code>
|
||||
* @ExtendWith(NotYetImplementedExtension.class)
|
||||
@@ -19,7 +22,7 @@ import java.lang.annotation.Target;
|
||||
* </p>
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.TYPE, ElementType.METHOD})
|
||||
@Target({ ElementType.TYPE, ElementType.METHOD })
|
||||
public @interface NotYetImplemented {
|
||||
String value() default "";
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
package jadx.core.dex.info;
|
||||
|
||||
import com.android.dx.rop.code.AccessFlags;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import com.android.dx.rop.code.AccessFlags;
|
||||
|
||||
import jadx.core.dex.info.AccessInfo.AFType;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
|
||||
@@ -1,5 +1,25 @@
|
||||
package jadx.tests.api;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.jar.JarOutputStream;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
|
||||
import jadx.api.JadxArgs;
|
||||
import jadx.api.JadxDecompiler;
|
||||
import jadx.api.JadxInternalAccess;
|
||||
@@ -19,25 +39,6 @@ import jadx.core.xmlgen.entry.ResourceEntry;
|
||||
import jadx.tests.api.compiler.DynamicCompiler;
|
||||
import jadx.tests.api.compiler.StaticCompiler;
|
||||
import jadx.tests.api.utils.TestUtils;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.jar.JarOutputStream;
|
||||
|
||||
import static jadx.core.utils.files.FileUtils.addFileToJar;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
@@ -60,8 +61,10 @@ public abstract class IntegrationTest extends TestUtils {
|
||||
|
||||
/**
|
||||
* Run auto check method if defined:
|
||||
*
|
||||
* <pre>
|
||||
* public void check() {}
|
||||
* public void check() {
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
private static final String CHECK_METHOD_NAME = "check";
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
package jadx.tests.api.compiler;
|
||||
|
||||
import javax.tools.SimpleJavaFileObject;
|
||||
import java.net.URI;
|
||||
|
||||
import javax.tools.SimpleJavaFileObject;
|
||||
|
||||
public class CharSequenceJavaFileObject extends SimpleJavaFileObject {
|
||||
|
||||
private CharSequence content;
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
package jadx.tests.api.compiler;
|
||||
|
||||
import java.security.SecureClassLoader;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import javax.tools.FileObject;
|
||||
import javax.tools.ForwardingJavaFileManager;
|
||||
import javax.tools.JavaFileObject;
|
||||
import javax.tools.StandardJavaFileManager;
|
||||
import java.io.IOException;
|
||||
import java.security.SecureClassLoader;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import static javax.tools.JavaFileObject.Kind;
|
||||
|
||||
@@ -21,8 +21,7 @@ public class ClassFileManager extends ForwardingJavaFileManager<StandardJavaFile
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaFileObject getJavaFileForOutput(Location location, String className,
|
||||
Kind kind, FileObject sibling) throws IOException {
|
||||
public JavaFileObject getJavaFileForOutput(Location location, String className, Kind kind, FileObject sibling) {
|
||||
JavaClassObject clsObject = new JavaClassObject(className, kind);
|
||||
classLoader.getClsMap().put(className, clsObject);
|
||||
return clsObject;
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
package jadx.tests.api.compiler;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.tools.JavaCompiler;
|
||||
import javax.tools.JavaFileManager;
|
||||
import javax.tools.JavaFileObject;
|
||||
import javax.tools.ToolProvider;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
package jadx.tests.api.compiler;
|
||||
|
||||
import javax.tools.SimpleJavaFileObject;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.net.URI;
|
||||
|
||||
import javax.tools.SimpleJavaFileObject;
|
||||
|
||||
public class JavaClassObject extends SimpleJavaFileObject {
|
||||
|
||||
protected final ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
|
||||
@@ -1,16 +1,5 @@
|
||||
package jadx.tests.api.compiler;
|
||||
|
||||
import jadx.core.utils.files.FileUtils;
|
||||
import org.eclipse.jdt.internal.compiler.tool.EclipseCompiler;
|
||||
|
||||
import javax.tools.FileObject;
|
||||
import javax.tools.ForwardingJavaFileManager;
|
||||
import javax.tools.JavaCompiler;
|
||||
import javax.tools.JavaCompiler.CompilationTask;
|
||||
import javax.tools.JavaFileObject;
|
||||
import javax.tools.SimpleJavaFileObject;
|
||||
import javax.tools.StandardJavaFileManager;
|
||||
import javax.tools.ToolProvider;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
@@ -20,11 +9,25 @@ import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import javax.tools.FileObject;
|
||||
import javax.tools.ForwardingJavaFileManager;
|
||||
import javax.tools.JavaCompiler;
|
||||
import javax.tools.JavaCompiler.CompilationTask;
|
||||
import javax.tools.JavaFileObject;
|
||||
import javax.tools.SimpleJavaFileObject;
|
||||
import javax.tools.StandardJavaFileManager;
|
||||
import javax.tools.ToolProvider;
|
||||
|
||||
import org.eclipse.jdt.internal.compiler.tool.EclipseCompiler;
|
||||
|
||||
import jadx.core.utils.files.FileUtils;
|
||||
|
||||
public class StaticCompiler {
|
||||
|
||||
private static final List<String> COMMON_ARGS = Arrays.asList("-source 1.8 -target 1.8".split(" "));
|
||||
|
||||
public static List<File> compile(List<File> files, File outDir, boolean includeDebugInfo, boolean useEclipseCompiler) throws IOException {
|
||||
public static List<File> compile(List<File> files, File outDir, boolean includeDebugInfo, boolean useEclipseCompiler)
|
||||
throws IOException {
|
||||
JavaCompiler compiler;
|
||||
if (useEclipseCompiler) {
|
||||
compiler = new EclipseCompiler();
|
||||
|
||||
@@ -54,7 +54,7 @@ public abstract class BaseExternalTest extends IntegrationTest {
|
||||
|
||||
if (clsPatternStr == null) {
|
||||
processAll(jadx);
|
||||
// jadx.saveSources();
|
||||
// jadx.saveSources();
|
||||
} else {
|
||||
processByPatterns(jadx, clsPatternStr, mthPatternStr);
|
||||
}
|
||||
@@ -161,8 +161,7 @@ public abstract class BaseExternalTest extends IntegrationTest {
|
||||
LOG.info("Print method: {}\n{}\n{}\n{}", mth.getMethodInfo().getShortId(),
|
||||
dashLine,
|
||||
mthCode,
|
||||
dashLine
|
||||
);
|
||||
dashLine);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ class SignatureParserTest {
|
||||
checkType("La/b/C<Ld/E<Lf/G;>;>;", generic("La/b/C;", generic("Ld/E;", object("Lf/G;"))));
|
||||
checkType("La<TD;>.c;", genericInner(generic("La;", genericType("D")), "c", null));
|
||||
checkType("La<TD;>.c/d;", genericInner(generic("La;", genericType("D")), "c.d", null));
|
||||
checkType("La<Lb;>.c<TV;>;", genericInner(generic("La;", object("Lb;")), "c", new ArgType[]{genericType("V")}));
|
||||
checkType("La<Lb;>.c<TV;>;", genericInner(generic("La;", object("Lb;")), "c", new ArgType[] { genericType("V") }));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -13,6 +13,7 @@ class StringUtilsTest {
|
||||
private StringUtils stringUtils;
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("AvoidEscapedUnicodeCharacters")
|
||||
public void testStringUnescape() {
|
||||
JadxArgs args = new JadxArgs();
|
||||
args.setEscapeUnicode(true);
|
||||
|
||||
@@ -18,7 +18,7 @@ public class TestClassGen extends IntegrationTest {
|
||||
public int test3();
|
||||
}
|
||||
|
||||
public static abstract class A {
|
||||
public abstract static class A {
|
||||
public abstract int test2();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ public class TestFloatValue extends IntegrationTest {
|
||||
|
||||
public static class TestCls {
|
||||
public float[] method() {
|
||||
float[] fa = {0.55f};
|
||||
float[] fa = { 0.55f };
|
||||
fa[0] /= 2;
|
||||
return fa;
|
||||
}
|
||||
|
||||
@@ -56,7 +56,8 @@ public class TestReturnWrapping extends IntegrationTest {
|
||||
assertThat(code, containsString("return arg0 + 1;"));
|
||||
|
||||
// TODO: reduce code vars by name
|
||||
// assertThat(code, containsString("return i > 128 ? arg0.toString() + ret.toString() : Integer.valueOf(i);"));
|
||||
// assertThat(code, containsString("return i > 128 ? arg0.toString() + ret.toString() :
|
||||
// Integer.valueOf(i);"));
|
||||
assertThat(code, containsString("return i2 > 128 ? arg0.toString() + ret.toString() : Integer.valueOf(i2);"));
|
||||
|
||||
assertThat(code, containsString("return arg0 + 2;"));
|
||||
|
||||
@@ -12,18 +12,18 @@ import static org.hamcrest.MatcherAssert.assertThat;
|
||||
public class TestStaticFieldsInit extends IntegrationTest {
|
||||
|
||||
public static class TestCls {
|
||||
public static final String s1 = "1";
|
||||
public static final String s2 = "12".substring(1);
|
||||
public static final String s3 = null;
|
||||
public static final String s4;
|
||||
public static final String s5 = "5";
|
||||
public static final String S1 = "1";
|
||||
public static final String S2 = "12".substring(1);
|
||||
public static final String S3 = null;
|
||||
public static final String S4;
|
||||
public static final String S5 = "5";
|
||||
public static String s6 = "6";
|
||||
|
||||
static {
|
||||
if (s5.equals("?")) {
|
||||
s4 = "?";
|
||||
if (S5.equals("?")) {
|
||||
S4 = "?";
|
||||
} else {
|
||||
s4 = "4";
|
||||
S4 = "4";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -33,7 +33,7 @@ public class TestStaticFieldsInit extends IntegrationTest {
|
||||
ClassNode cls = getClassNode(TestCls.class);
|
||||
String code = cls.getCode().toString();
|
||||
|
||||
assertThat(code, not(containsString("public static final String s2 = null;")));
|
||||
assertThat(code, containsString("public static final String s3 = null;"));
|
||||
assertThat(code, not(containsString("public static final String S2 = null;")));
|
||||
assertThat(code, containsString("public static final String S3 = null;"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,8 +18,8 @@ public class TestStringBuilderElimination2 extends IntegrationTest {
|
||||
|
||||
public static class TestCls1 {
|
||||
public String test() {
|
||||
return new StringBuilder("[init]").append("a1").append('c').append(2).append(0L).append(1.0f).
|
||||
append(2.0d).append(true).toString();
|
||||
return new StringBuilder("[init]").append("a1").append('c').append(2).append(0L).append(1.0f).append(2.0d).append(true)
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,8 +41,7 @@ public class TestStringBuilderElimination2 extends IntegrationTest {
|
||||
float f = 1.0f;
|
||||
double d = 2.0d;
|
||||
boolean b = true;
|
||||
return new StringBuilder(sInit).append(s).append(c).append(i).append(l).append(f).
|
||||
append(d).append(b).toString();
|
||||
return new StringBuilder(sInit).append(s).append(c).append(i).append(l).append(f).append(d).append(b).toString();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -39,8 +39,7 @@ public class TestWrongCode extends IntegrationTest {
|
||||
assertThat(code, containsLines(2,
|
||||
"if (a == 0) {",
|
||||
"}",
|
||||
"return a;"
|
||||
));
|
||||
"return a;"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -17,7 +17,7 @@ public class TestAnnotations2 extends IntegrationTest {
|
||||
|
||||
public static class TestCls {
|
||||
|
||||
@Target({ElementType.TYPE})
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface A {
|
||||
int i();
|
||||
|
||||
@@ -56,12 +56,14 @@ public class TestAnnotationsMix extends IntegrationTest {
|
||||
return Arrays.asList(a);
|
||||
}
|
||||
|
||||
@MyAnnotation(name = "b",
|
||||
@MyAnnotation(
|
||||
name = "b",
|
||||
num = 7,
|
||||
cls = Exception.class,
|
||||
doubles = {0.0, 1.1},
|
||||
doubles = { 0.0, 1.1 },
|
||||
value = 9.87f,
|
||||
simple = @SimpleAnnotation(false))
|
||||
simple = @SimpleAnnotation(false)
|
||||
)
|
||||
public static Object test(String[] a) {
|
||||
return Arrays.asList(a);
|
||||
}
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@ public class TestAnnotationsRename extends IntegrationTest {
|
||||
|
||||
public static class TestCls {
|
||||
|
||||
@Target({ElementType.METHOD})
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface A {
|
||||
int x();
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@ public class TestAnnotationsRenameDef extends IntegrationTest {
|
||||
|
||||
public static class TestCls {
|
||||
|
||||
@Target({ElementType.METHOD})
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface A {
|
||||
int value();
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@ public class TestParamAnnotations extends IntegrationTest {
|
||||
|
||||
public static class TestCls {
|
||||
|
||||
@Target({ElementType.PARAMETER})
|
||||
@Target(ElementType.PARAMETER)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public static @interface A {
|
||||
int i() default 7;
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
package jadx.tests.integration.arith;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import jadx.NotYetImplemented;
|
||||
import jadx.core.dex.nodes.ClassNode;
|
||||
import jadx.tests.api.IntegrationTest;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
|
||||
public class TestArith extends IntegrationTest {
|
||||
|
||||
public static class TestCls {
|
||||
@@ -25,7 +25,8 @@ public class TestArith extends IntegrationTest {
|
||||
return a;
|
||||
}
|
||||
|
||||
private static void use(int i) {}
|
||||
private static void use(int i) {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
package jadx.tests.integration.arith;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
import static org.hamcrest.CoreMatchers.not;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import jadx.core.dex.nodes.ClassNode;
|
||||
import jadx.tests.api.IntegrationTest;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
import static org.hamcrest.CoreMatchers.not;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
|
||||
public class TestArith2 extends IntegrationTest {
|
||||
|
||||
public static class TestCls {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user