Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
J
jadx
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
open-source
jadx
Commits
a3464d71
Commit
a3464d71
authored
Oct 28, 2018
by
Skylot
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix(gui): make link for full class names (#378)
parent
a8a31643
Show whitespace changes
Inline
Side-by-side
Showing
23 changed files
with
602 additions
and
102 deletions
+602
-102
JadxDecompiler.java
jadx-core/src/main/java/jadx/api/JadxDecompiler.java
+28
-0
JavaClass.java
jadx-core/src/main/java/jadx/api/JavaClass.java
+3
-12
ClassGen.java
jadx-core/src/main/java/jadx/core/codegen/ClassGen.java
+6
-24
JadxSettings.java
jadx-gui/src/main/java/jadx/gui/settings/JadxSettings.java
+2
-2
JadxSettingsWindow.java
...i/src/main/java/jadx/gui/settings/JadxSettingsWindow.java
+2
-3
CertificatePanel.java
jadx-gui/src/main/java/jadx/gui/ui/CertificatePanel.java
+1
-0
CommonSearchDialog.java
jadx-gui/src/main/java/jadx/gui/ui/CommonSearchDialog.java
+3
-2
ContentPanel.java
jadx-gui/src/main/java/jadx/gui/ui/ContentPanel.java
+4
-4
LogViewer.java
jadx-gui/src/main/java/jadx/gui/ui/LogViewer.java
+1
-0
MainWindow.java
jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java
+2
-2
TabbedPane.java
jadx-gui/src/main/java/jadx/gui/ui/TabbedPane.java
+11
-9
CodeArea.java
jadx-gui/src/main/java/jadx/gui/ui/codearea/CodeArea.java
+204
-0
CodeLinkGenerator.java
...src/main/java/jadx/gui/ui/codearea/CodeLinkGenerator.java
+88
-0
CodePanel.java
jadx-gui/src/main/java/jadx/gui/ui/codearea/CodePanel.java
+8
-6
EditorTheme.java
jadx-gui/src/main/java/jadx/gui/ui/codearea/EditorTheme.java
+40
-0
FindUsageAction.java
...i/src/main/java/jadx/gui/ui/codearea/FindUsageAction.java
+67
-0
JadxTokenMaker.java
...ui/src/main/java/jadx/gui/ui/codearea/JadxTokenMaker.java
+105
-0
LineNumbers.java
jadx-gui/src/main/java/jadx/gui/ui/codearea/LineNumbers.java
+1
-1
SearchBar.java
jadx-gui/src/main/java/jadx/gui/ui/codearea/SearchBar.java
+2
-7
JumpManager.java
jadx-gui/src/main/java/jadx/gui/utils/JumpManager.java
+6
-6
JumpPosition.java
jadx-gui/src/main/java/jadx/gui/utils/JumpPosition.java
+4
-11
Messages_en_US.properties
jadx-gui/src/main/resources/i18n/Messages_en_US.properties
+1
-0
TestJumpManager.groovy
...gui/src/test/groovy/jadx/gui/tests/TestJumpManager.groovy
+13
-13
No files found.
jadx-core/src/main/java/jadx/api/JadxDecompiler.java
View file @
a3464d71
...
...
@@ -311,10 +311,38 @@ public final class JadxDecompiler {
return
methodsMap
;
}
JavaMethod
getJavaMethodByNode
(
MethodNode
mth
)
{
JavaMethod
javaMethod
=
methodsMap
.
get
(
mth
);
if
(
javaMethod
!=
null
)
{
return
javaMethod
;
}
// parent class not loaded yet
JavaClass
javaClass
=
classesMap
.
get
(
mth
.
getParentClass
());
if
(
javaClass
!=
null
)
{
javaClass
.
decompile
();
return
methodsMap
.
get
(
mth
);
}
return
null
;
}
Map
<
FieldNode
,
JavaField
>
getFieldsMap
()
{
return
fieldsMap
;
}
JavaField
getJavaFieldByNode
(
FieldNode
fld
)
{
JavaField
javaField
=
fieldsMap
.
get
(
fld
);
if
(
javaField
!=
null
)
{
return
javaField
;
}
// parent class not loaded yet
JavaClass
javaClass
=
classesMap
.
get
(
fld
.
getParentClass
());
if
(
javaClass
!=
null
)
{
javaClass
.
decompile
();
return
fieldsMap
.
get
(
fld
);
}
return
null
;
}
public
JadxArgs
getArgs
()
{
return
args
;
}
...
...
jadx-core/src/main/java/jadx/api/JavaClass.java
View file @
a3464d71
...
...
@@ -160,10 +160,10 @@ public final class JavaClass implements JavaNode {
return
getRootDecompiler
().
getClassesMap
().
get
(
obj
);
}
if
(
obj
instanceof
MethodNode
)
{
return
getRootDecompiler
().
get
MethodsMap
().
get
(
obj
);
return
getRootDecompiler
().
get
JavaMethodByNode
(((
MethodNode
)
obj
)
);
}
if
(
obj
instanceof
FieldNode
)
{
return
getRootDecompiler
().
get
FieldsMap
().
get
(
obj
);
return
getRootDecompiler
().
get
JavaFieldByNode
((
FieldNode
)
obj
);
}
return
null
;
}
...
...
@@ -182,15 +182,6 @@ public final class JavaClass implements JavaNode {
}
@Nullable
public
CodePosition
getDefinitionPosition
(
int
line
,
int
offset
)
{
JavaNode
javaNode
=
getJavaNodeAtPosition
(
line
,
offset
);
if
(
javaNode
==
null
)
{
return
null
;
}
return
getDefinitionPosition
(
javaNode
);
}
@Nullable
public
CodePosition
getDefinitionPosition
(
JavaNode
javaNode
)
{
JavaClass
jCls
=
javaNode
.
getTopParentClass
();
jCls
.
decompile
();
...
...
@@ -265,6 +256,6 @@ public final class JavaClass implements JavaNode {
@Override
public
String
toString
()
{
return
cls
.
getFullName
()
+
"[ "
+
getFullName
()
+
" ]"
;
return
getFullName
()
;
}
}
jadx-core/src/main/java/jadx/core/codegen/ClassGen.java
View file @
a3464d71
package
jadx
.
core
.
codegen
;
import
java.util.ArrayList
;
import
java.util.Collections
;
import
java.util.Comparator
;
import
java.util.HashSet
;
import
java.util.Iterator
;
...
...
@@ -84,35 +83,18 @@ public class ClassGen {
}
int
importsCount
=
imports
.
size
();
if
(
importsCount
!=
0
)
{
List
<
String
>
sortImports
=
new
ArrayList
<>(
importsCount
);
for
(
ClassInfo
ic
:
imports
)
{
sortImports
.
add
(
ic
.
getAlias
().
getFullName
());
}
Collections
.
sort
(
sortImports
);
for
(
String
imp
:
sortImports
)
{
ClassInfo
importClassInfo
=
ClassInfo
.
fromName
(
cls
.
dex
().
root
(),
imp
);
ClassNode
classNode
=
cls
.
dex
().
resolveClass
(
importClassInfo
);
// Clickable element seems to be limited by the next dot, therefore
// we can't just use the complete class name including packagename
int
clsDotIdx
=
imp
.
lastIndexOf
(
'.'
);
String
pkg
=
""
;
if
(
clsDotIdx
>=
0
)
{
pkg
=
imp
.
substring
(
0
,
clsDotIdx
+
1
);
imp
=
imp
.
substring
(
clsDotIdx
+
1
);
}
List
<
ClassInfo
>
sortedImports
=
new
ArrayList
<>(
imports
);
sortedImports
.
sort
(
Comparator
.
comparing
(
classInfo
->
classInfo
.
getAlias
().
getFullName
()));
sortedImports
.
forEach
(
classInfo
->
{
clsCode
.
startLine
(
"import "
);
clsCode
.
add
(
pkg
);
ClassNode
classNode
=
cls
.
root
().
resolveClass
(
classInfo
);
if
(
classNode
!=
null
)
{
// attach the clickable link info to the class name
clsCode
.
attachAnnotation
(
classNode
);
}
clsCode
.
add
(
imp
);
clsCode
.
add
(
classInfo
.
getAlias
().
getFullName
()
);
clsCode
.
add
(
';'
);
}
}
);
clsCode
.
newLine
();
sortImports
.
clear
();
imports
.
clear
();
}
clsCode
.
add
(
clsBody
);
...
...
jadx-gui/src/main/java/jadx/gui/settings/JadxSettings.java
View file @
a3464d71
...
...
@@ -15,7 +15,7 @@ import org.slf4j.LoggerFactory;
import
jadx.api.JadxArgs
;
import
jadx.cli.JadxCLIArgs
;
import
jadx.gui.ui.
CodeArea
;
import
jadx.gui.ui.
codearea.EditorTheme
;
import
jadx.gui.utils.LangLocale
;
import
jadx.gui.utils.NLS
;
...
...
@@ -263,7 +263,7 @@ public class JadxSettings extends JadxCLIArgs {
fromVersion
++;
}
if
(
fromVersion
==
1
)
{
setEditorThemePath
(
CodeArea
.
getAllThemes
()
[
0
].
getPath
());
setEditorThemePath
(
EditorTheme
.
ALL_THEMES
[
0
].
getPath
());
fromVersion
++;
}
if
(
fromVersion
==
2
)
{
...
...
jadx-gui/src/main/java/jadx/gui/settings/JadxSettingsWindow.java
View file @
a3464d71
...
...
@@ -12,8 +12,7 @@ import org.slf4j.Logger;
import
org.slf4j.LoggerFactory
;
import
say.swing.JFontChooser
;
import
jadx.gui.ui.CodeArea
;
import
jadx.gui.ui.CodeArea.EditorTheme
;
import
jadx.gui.ui.codearea.EditorTheme
;
import
jadx.gui.ui.MainWindow
;
import
jadx.gui.utils.LangLocale
;
import
jadx.gui.utils.NLS
;
...
...
@@ -191,7 +190,7 @@ public class JadxSettingsWindow extends JDialog {
}
});
EditorTheme
[]
editorThemes
=
CodeArea
.
getAllThemes
()
;
EditorTheme
[]
editorThemes
=
EditorTheme
.
ALL_THEMES
;
JComboBox
<
EditorTheme
>
themesCbx
=
new
JComboBox
<>(
editorThemes
);
for
(
EditorTheme
theme
:
editorThemes
)
{
if
(
theme
.
getPath
().
equals
(
settings
.
getEditorThemePath
()))
{
...
...
jadx-gui/src/main/java/jadx/gui/ui/CertificatePanel.java
View file @
a3464d71
...
...
@@ -6,6 +6,7 @@ import java.awt.*;
import
org.fife.ui.rsyntaxtextarea.RSyntaxTextArea
;
import
jadx.gui.treemodel.JNode
;
import
jadx.gui.ui.codearea.CodeArea
;
public
final
class
CertificatePanel
extends
ContentPanel
{
private
static
final
long
serialVersionUID
=
8566591625905036877L
;
...
...
jadx-gui/src/main/java/jadx/gui/ui/CommonSearchDialog.java
View file @
a3464d71
...
...
@@ -31,9 +31,10 @@ import jadx.gui.jobs.BackgroundJob;
import
jadx.gui.jobs.BackgroundWorker
;
import
jadx.gui.jobs.DecompileJob
;
import
jadx.gui.treemodel.JNode
;
import
jadx.gui.ui.codearea.CodeArea
;
import
jadx.gui.utils.CacheObject
;
import
jadx.gui.utils.NLS
;
import
jadx.gui.utils.Position
;
import
jadx.gui.utils.
Jump
Position
;
import
jadx.gui.utils.search.TextSearchIndex
;
public
abstract
class
CommonSearchDialog
extends
JDialog
{
...
...
@@ -106,7 +107,7 @@ public abstract class CommonSearchDialog extends JDialog {
return
;
}
JNode
node
=
(
JNode
)
resultsModel
.
getValueAt
(
selectedId
,
0
);
tabbedPane
.
codeJump
(
new
Position
(
node
.
getRootClass
(),
node
.
getLine
()));
tabbedPane
.
codeJump
(
new
Jump
Position
(
node
.
getRootClass
(),
node
.
getLine
()));
dispose
();
}
...
...
jadx-gui/src/main/java/jadx/gui/ui/ContentPanel.java
View file @
a3464d71
...
...
@@ -4,25 +4,25 @@ import javax.swing.*;
import
jadx.gui.treemodel.JNode
;
abstract
class
ContentPanel
extends
JPanel
{
public
abstract
class
ContentPanel
extends
JPanel
{
private
static
final
long
serialVersionUID
=
3237031760631677822L
;
protected
final
TabbedPane
tabbedPane
;
protected
final
JNode
node
;
ContentPanel
(
TabbedPane
panel
,
JNode
jnode
)
{
protected
ContentPanel
(
TabbedPane
panel
,
JNode
jnode
)
{
tabbedPane
=
panel
;
node
=
jnode
;
}
public
abstract
void
loadSettings
();
TabbedPane
getTabbedPane
()
{
public
TabbedPane
getTabbedPane
()
{
return
tabbedPane
;
}
JNode
getNode
()
{
public
JNode
getNode
()
{
return
node
;
}
}
jadx-gui/src/main/java/jadx/gui/ui/LogViewer.java
View file @
a3464d71
...
...
@@ -7,6 +7,7 @@ import ch.qos.logback.classic.Level;
import
org.fife.ui.rsyntaxtextarea.RSyntaxTextArea
;
import
jadx.gui.settings.JadxSettings
;
import
jadx.gui.ui.codearea.CodeArea
;
import
jadx.gui.utils.NLS
;
import
jadx.gui.utils.logs.ILogListener
;
import
jadx.gui.utils.logs.LogCollector
;
...
...
jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java
View file @
a3464d71
...
...
@@ -51,7 +51,7 @@ import jadx.gui.update.data.Release;
import
jadx.gui.utils.CacheObject
;
import
jadx.gui.utils.Link
;
import
jadx.gui.utils.NLS
;
import
jadx.gui.utils.Position
;
import
jadx.gui.utils.
Jump
Position
;
import
jadx.gui.utils.Utils
;
import
static
javax
.
swing
.
KeyStroke
.
getKeyStroke
;
...
...
@@ -300,7 +300,7 @@ public class MainWindow extends JFrame {
JNode
node
=
(
JNode
)
obj
;
JClass
cls
=
node
.
getRootClass
();
if
(
cls
!=
null
)
{
tabbedPane
.
codeJump
(
new
Position
(
cls
,
node
.
getLine
()));
tabbedPane
.
codeJump
(
new
Jump
Position
(
cls
,
node
.
getLine
()));
}
}
}
catch
(
Exception
e
)
{
...
...
jadx-gui/src/main/java/jadx/gui/ui/TabbedPane.java
View file @
a3464d71
...
...
@@ -21,12 +21,14 @@ import jadx.gui.treemodel.JCertificate;
import
jadx.gui.treemodel.JClass
;
import
jadx.gui.treemodel.JNode
;
import
jadx.gui.treemodel.JResource
;
import
jadx.gui.ui.codearea.CodeArea
;
import
jadx.gui.ui.codearea.CodePanel
;
import
jadx.gui.utils.JumpManager
;
import
jadx.gui.utils.JumpPosition
;
import
jadx.gui.utils.NLS
;
import
jadx.gui.utils.Position
;
import
jadx.gui.utils.Utils
;
class
TabbedPane
extends
JTabbedPane
{
public
class
TabbedPane
extends
JTabbedPane
{
private
static
final
Logger
LOG
=
LoggerFactory
.
getLogger
(
TabbedPane
.
class
);
private
static
final
long
serialVersionUID
=
-
8833600618794570904L
;
...
...
@@ -57,11 +59,11 @@ class TabbedPane extends JTabbedPane {
});
}
MainWindow
getMainWindow
()
{
public
MainWindow
getMainWindow
()
{
return
mainWindow
;
}
private
void
showCode
(
final
Position
pos
)
{
private
void
showCode
(
final
Jump
Position
pos
)
{
final
CodePanel
contentPanel
=
(
CodePanel
)
getContentPanel
(
pos
.
getNode
());
if
(
contentPanel
==
null
)
{
return
;
...
...
@@ -99,8 +101,8 @@ class TabbedPane extends JTabbedPane {
SwingUtilities
.
invokeLater
(()
->
setSelectedComponent
(
contentPanel
));
}
public
void
codeJump
(
Position
pos
)
{
Position
curPos
=
getCurrentPosition
();
public
void
codeJump
(
Jump
Position
pos
)
{
Jump
Position
curPos
=
getCurrentPosition
();
if
(
curPos
!=
null
)
{
jumps
.
addPosition
(
curPos
);
jumps
.
addPosition
(
pos
);
...
...
@@ -109,7 +111,7 @@ class TabbedPane extends JTabbedPane {
}
@Nullable
private
Position
getCurrentPosition
()
{
private
Jump
Position
getCurrentPosition
()
{
ContentPanel
selectedCodePanel
=
getSelectedCodePanel
();
if
(
selectedCodePanel
instanceof
CodePanel
)
{
return
((
CodePanel
)
selectedCodePanel
).
getCodeArea
().
getCurrentPosition
();
...
...
@@ -118,14 +120,14 @@ class TabbedPane extends JTabbedPane {
}
public
void
navBack
()
{
Position
pos
=
jumps
.
getPrev
();
Jump
Position
pos
=
jumps
.
getPrev
();
if
(
pos
!=
null
)
{
showCode
(
pos
);
}
}
public
void
navForward
()
{
Position
pos
=
jumps
.
getNext
();
Jump
Position
pos
=
jumps
.
getNext
();
if
(
pos
!=
null
)
{
showCode
(
pos
);
}
...
...
jadx-gui/src/main/java/jadx/gui/ui/CodeArea.java
→
jadx-gui/src/main/java/jadx/gui/ui/
codearea/
CodeArea.java
View file @
a3464d71
package
jadx
.
gui
.
ui
;
package
jadx
.
gui
.
ui
.
codearea
;
import
javax.swing.*
;
import
javax.swing.event.HyperlinkEvent
;
import
javax.swing.event.HyperlinkListener
;
import
javax.swing.event.PopupMenuEvent
;
import
javax.swing.event.PopupMenuListener
;
import
javax.swing.text.BadLocationException
;
import
javax.swing.text.Caret
;
import
javax.swing.text.DefaultCaret
;
import
java.awt.*
;
import
java.awt.event.ActionEvent
;
import
java.awt.event.MouseAdapter
;
import
java.awt.event.MouseEvent
;
import
org.fife.ui.rsyntaxtextarea.LinkGenerator
;
import
org.fife.ui.rsyntaxtextarea.LinkGeneratorResult
;
import
org.fife.ui.rsyntaxtextarea.RSyntaxDocument
;
import
org.fife.ui.rsyntaxtextarea.RSyntaxTextArea
;
import
org.fife.ui.rsyntaxtextarea.Token
;
import
org.fife.ui.rsyntaxtextarea.TokenTypes
;
import
org.fife.ui.rtextarea.SearchContext
;
import
org.fife.ui.rtextarea.SearchEngine
;
import
org.jetbrains.annotations.Nullable
;
...
...
@@ -29,7 +22,8 @@ import jadx.api.JavaNode;
import
jadx.gui.settings.JadxSettings
;
import
jadx.gui.treemodel.JClass
;
import
jadx.gui.treemodel.JNode
;
import
jadx.gui.utils.Position
;
import
jadx.gui.ui.MainWindow
;
import
jadx.gui.utils.JumpPosition
;
public
final
class
CodeArea
extends
RSyntaxTextArea
{
private
static
final
Logger
LOG
=
LoggerFactory
.
getLogger
(
CodeArea
.
class
);
...
...
@@ -55,11 +49,14 @@ public final class CodeArea extends RSyntaxTextArea {
setSyntaxEditingStyle
(
node
.
getSyntaxName
());
if
(
node
instanceof
JClass
)
{
JClass
jClsNode
=
(
JClass
)
this
.
node
;
((
RSyntaxDocument
)
getDocument
()).
setSyntaxStyle
(
new
JadxTokenMaker
(
this
,
jClsNode
));
setHyperlinksEnabled
(
true
);
CodeLinkGenerator
codeLinkProcessor
=
new
CodeLinkGenerator
(
(
JClass
)
n
ode
);
CodeLinkGenerator
codeLinkProcessor
=
new
CodeLinkGenerator
(
contentPanel
,
this
,
jClsN
ode
);
setLinkGenerator
(
codeLinkProcessor
);
addHyperlinkListener
(
codeLinkProcessor
);
addMenuItems
(
this
,
(
JClass
)
n
ode
);
addMenuItems
(
jClsN
ode
);
}
registerWordHighlighter
();
setText
(
node
.
getContent
());
...
...
@@ -93,8 +90,8 @@ public final class CodeArea extends RSyntaxTextArea {
SearchEngine
.
markAll
(
this
,
context
);
}
private
void
addMenuItems
(
CodeArea
codeArea
,
JClass
jCls
)
{
Action
findUsage
=
new
FindUsageAction
(
co
deArea
,
jCls
);
private
void
addMenuItems
(
JClass
jCls
)
{
Action
findUsage
=
new
FindUsageAction
(
co
ntentPanel
,
this
,
jCls
);
JPopupMenu
popup
=
getPopupMenu
();
popup
.
addSeparator
();
...
...
@@ -120,75 +117,48 @@ public final class CodeArea extends RSyntaxTextArea {
return
area
;
}
private
boolean
isJumpToken
(
Token
token
)
{
if
(
token
.
getType
()
==
TokenTypes
.
IDENTIFIER
)
{
// fast skip
if
(
token
.
length
()
==
1
)
{
char
ch
=
token
.
getTextArray
()[
token
.
getTextOffset
()];
if
(
ch
==
'.'
||
ch
==
','
||
ch
==
';'
)
{
return
false
;
}
}
if
(
node
instanceof
JClass
)
{
Position
pos
=
getDefPosition
((
JClass
)
node
,
this
,
token
.
getOffset
());
if
(
pos
!=
null
)
{
// don't underline definition place
try
{
int
defLine
=
pos
.
getLine
();
int
lineOfOffset
=
getLineOfOffset
(
token
.
getOffset
())
+
1
;
if
(
defLine
==
lineOfOffset
)
{
return
false
;
}
}
catch
(
BadLocationException
e
)
{
return
false
;
}
return
true
;
}
}
}
return
false
;
}
// @Override
// public Color getForegroundForToken(Token t) {
// if (isJumpToken(t)) {
// return getHyperlinkForeground();
// }
// return super.getForegroundForToken(t);
// }
static
Position
getDefPosition
(
JClass
jCls
,
RSyntaxTextArea
textArea
,
int
offset
)
{
JavaNode
node
=
getJavaNodeAtOffset
(
jCls
,
textArea
,
offset
);
if
(
node
==
null
)
{
/**
* Search node by offset in {@code jCls} code and return its definition position
* (useful for jumps from usage)
*/
public
JumpPosition
getDefPosForNodeAtOffset
(
JClass
jCls
,
int
offset
)
{
JavaNode
foundNode
=
getJavaNodeAtOffset
(
jCls
,
offset
);
if
(
foundNode
==
null
)
{
return
null
;
}
CodePosition
pos
=
jCls
.
getCls
().
getDefinitionPosition
(
n
ode
);
CodePosition
pos
=
jCls
.
getCls
().
getDefinitionPosition
(
foundN
ode
);
if
(
pos
==
null
)
{
return
null
;
}
return
new
Position
(
pos
);
JNode
jNode
=
contentPanel
.
getTabbedPane
().
getMainWindow
().
getCacheObject
().
getNodeCache
().
makeFrom
(
foundNode
);
return
new
JumpPosition
(
jNode
.
getRootClass
(),
pos
.
getLine
());
}
static
JavaNode
getJavaNodeAtOffset
(
JClass
jCls
,
RSyntaxTextArea
textArea
,
int
offset
)
{
/**
* Search referenced java node by offset in {@code jCls} code
*/
public
JavaNode
getJavaNodeAtOffset
(
JClass
jCls
,
int
offset
)
{
try
{
int
line
=
textArea
.
getLineOfOffset
(
offset
);
int
lineOffset
=
offset
-
textArea
.
getLineStartOffset
(
line
);
// TODO: add direct mapping for code offset to CodeWriter (instead of line and line offset pair)
int
line
=
this
.
getLineOfOffset
(
offset
);
int
lineOffset
=
offset
-
this
.
getLineStartOffset
(
line
);
return
jCls
.
getCls
().
getJavaNodeAtPosition
(
line
+
1
,
lineOffset
+
1
);
}
catch
(
BadLocation
Exception
e
)
{
LOG
.
error
(
"Can't get java node by offset
"
,
e
);
}
catch
(
Exception
e
)
{
LOG
.
error
(
"Can't get java node by offset
: {}"
,
offset
,
e
);
}
return
null
;
}
public
Position
getCurrentPosition
()
{
return
new
Position
(
node
,
getCaretLineNumber
()
+
1
);
public
Jump
Position
getCurrentPosition
()
{
return
new
Jump
Position
(
node
,
getCaretLineNumber
()
+
1
);
}
@Nullable
Integer
getSourceLine
(
int
line
)
{
return
node
.
getSourceLine
(
line
);
}
void
scrollToLine
(
int
line
)
{
public
void
scrollToLine
(
int
line
)
{
int
lineNum
=
line
-
1
;
if
(
lineNum
<
0
)
{
lineNum
=
0
;
...
...
@@ -231,131 +201,4 @@ public final class CodeArea extends RSyntaxTextArea {
LOG
.
debug
(
"Can't scroll to {}"
,
line
,
e
);
}
}
private
class
FindUsageAction
extends
AbstractAction
implements
PopupMenuListener
{
private
static
final
long
serialVersionUID
=
4692546569977976384L
;
private
final
transient
CodeArea
codeArea
;
private
final
transient
JClass
jCls
;
private
transient
JavaNode
node
;
public
FindUsageAction
(
CodeArea
codeArea
,
JClass
jCls
)
{
super
(
"Find Usage"
);
this
.
codeArea
=
codeArea
;
this
.
jCls
=
jCls
;
}
@Override
public
void
actionPerformed
(
ActionEvent
e
)
{
if
(
node
==
null
)
{
return
;
}
MainWindow
mainWindow
=
contentPanel
.
getTabbedPane
().
getMainWindow
();
JNode
jNode
=
mainWindow
.
getCacheObject
().
getNodeCache
().
makeFrom
(
node
);
UsageDialog
usageDialog
=
new
UsageDialog
(
mainWindow
,
jNode
);
usageDialog
.
setVisible
(
true
);
}
@Override
public
void
popupMenuWillBecomeVisible
(
PopupMenuEvent
e
)
{
node
=
null
;
Point
pos
=
codeArea
.
getMousePosition
();
if
(
pos
!=
null
)
{
Token
token
=
codeArea
.
viewToToken
(
pos
);
if
(
token
!=
null
)
{
node
=
getJavaNodeAtOffset
(
jCls
,
codeArea
,
token
.
getOffset
());
}
}
setEnabled
(
node
!=
null
);
}
@Override
public
void
popupMenuWillBecomeInvisible
(
PopupMenuEvent
e
)
{
}
@Override
public
void
popupMenuCanceled
(
PopupMenuEvent
e
)
{
}
}
private
class
CodeLinkGenerator
implements
LinkGenerator
,
HyperlinkListener
{
private
final
JClass
jCls
;
public
CodeLinkGenerator
(
JClass
cls
)
{
this
.
jCls
=
cls
;
}
@Override
public
LinkGeneratorResult
isLinkAtOffset
(
RSyntaxTextArea
textArea
,
int
offset
)
{
try
{
Token
token
=
textArea
.
modelToToken
(
offset
);
if
(
token
==
null
)
{
return
null
;
}
final
int
sourceOffset
=
token
.
getOffset
();
final
Position
defPos
=
getDefPosition
(
jCls
,
textArea
,
sourceOffset
);
if
(
defPos
==
null
)
{
return
null
;
}
return
new
LinkGeneratorResult
()
{
@Override
public
HyperlinkEvent
execute
()
{
return
new
HyperlinkEvent
(
defPos
,
HyperlinkEvent
.
EventType
.
ACTIVATED
,
null
,
defPos
.
getNode
().
makeLongString
());
}
@Override
public
int
getSourceOffset
()
{
return
sourceOffset
;
}
};
}
catch
(
Exception
e
)
{
LOG
.
error
(
"isLinkAtOffset error"
,
e
);
return
null
;
}
}
@Override
public
void
hyperlinkUpdate
(
HyperlinkEvent
e
)
{
Object
obj
=
e
.
getSource
();
if
(
obj
instanceof
Position
)
{
contentPanel
.
getTabbedPane
().
codeJump
((
Position
)
obj
);
}
}
}
public
static
final
class
EditorTheme
{
private
final
String
name
;
private
final
String
path
;
public
EditorTheme
(
String
name
,
String
path
)
{
this
.
name
=
name
;
this
.
path
=
path
;
}
public
String
getName
()
{
return
name
;
}
public
String
getPath
()
{
return
path
;
}
@Override
public
String
toString
()
{
return
name
;
}
}
public
static
EditorTheme
[]
getAllThemes
()
{
return
new
EditorTheme
[]{
new
EditorTheme
(
"default"
,
"/org/fife/ui/rsyntaxtextarea/themes/default.xml"
),
new
EditorTheme
(
"eclipse"
,
"/org/fife/ui/rsyntaxtextarea/themes/eclipse.xml"
),
new
EditorTheme
(
"idea"
,
"/org/fife/ui/rsyntaxtextarea/themes/idea.xml"
),
new
EditorTheme
(
"vs"
,
"/org/fife/ui/rsyntaxtextarea/themes/vs.xml"
),
new
EditorTheme
(
"dark"
,
"/org/fife/ui/rsyntaxtextarea/themes/dark.xml"
),
new
EditorTheme
(
"monokai"
,
"/org/fife/ui/rsyntaxtextarea/themes/monokai.xml"
)
};
}
}
jadx-gui/src/main/java/jadx/gui/ui/codearea/CodeLinkGenerator.java
0 → 100644
View file @
a3464d71
package
jadx
.
gui
.
ui
.
codearea
;
import
javax.swing.event.HyperlinkEvent
;
import
javax.swing.event.HyperlinkListener
;
import
java.util.Objects
;
import
org.fife.ui.rsyntaxtextarea.LinkGenerator
;
import
org.fife.ui.rsyntaxtextarea.LinkGeneratorResult
;
import
org.fife.ui.rsyntaxtextarea.RSyntaxTextArea
;
import
org.fife.ui.rsyntaxtextarea.Token
;
import
org.fife.ui.rsyntaxtextarea.TokenTypes
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
jadx.gui.treemodel.JClass
;
import
jadx.gui.utils.JumpPosition
;
public
class
CodeLinkGenerator
implements
LinkGenerator
,
HyperlinkListener
{
private
static
final
Logger
LOG
=
LoggerFactory
.
getLogger
(
CodeLinkGenerator
.
class
);
private
final
CodePanel
contentPanel
;
private
final
CodeArea
codeArea
;
private
final
JClass
jCls
;
public
CodeLinkGenerator
(
CodePanel
contentPanel
,
CodeArea
codeArea
,
JClass
cls
)
{
this
.
contentPanel
=
contentPanel
;
this
.
codeArea
=
codeArea
;
this
.
jCls
=
cls
;
}
@Override
public
LinkGeneratorResult
isLinkAtOffset
(
RSyntaxTextArea
textArea
,
int
offset
)
{
try
{
Token
token
=
textArea
.
modelToToken
(
offset
);
if
(
token
==
null
)
{
return
null
;
}
int
type
=
token
.
getType
();
final
int
sourceOffset
;
if
(
type
==
TokenTypes
.
IDENTIFIER
)
{
sourceOffset
=
token
.
getOffset
();
}
else
if
(
type
==
TokenTypes
.
ANNOTATION
&&
token
.
length
()
>
1
)
{
sourceOffset
=
token
.
getOffset
()
+
1
;
}
else
{
return
null
;
}
// fast skip
if
(
token
.
length
()
==
1
)
{
char
ch
=
token
.
getTextArray
()[
token
.
getTextOffset
()];
if
(
ch
==
'.'
||
ch
==
','
||
ch
==
';'
)
{
return
null
;
}
}
final
JumpPosition
defPos
=
codeArea
.
getDefPosForNodeAtOffset
(
jCls
,
sourceOffset
);
if
(
defPos
==
null
)
{
return
null
;
}
if
(
Objects
.
equals
(
defPos
.
getNode
().
getRootClass
(),
jCls
)
&&
defPos
.
getLine
()
==
textArea
.
getLineOfOffset
(
sourceOffset
)
+
1
)
{
// ignore self jump
return
null
;
}
return
new
LinkGeneratorResult
()
{
@Override
public
HyperlinkEvent
execute
()
{
return
new
HyperlinkEvent
(
defPos
,
HyperlinkEvent
.
EventType
.
ACTIVATED
,
null
,
defPos
.
getNode
().
makeLongString
());
}
@Override
public
int
getSourceOffset
()
{
return
sourceOffset
;
}
};
}
catch
(
Exception
e
)
{
LOG
.
error
(
"isLinkAtOffset error"
,
e
);
return
null
;
}
}
@Override
public
void
hyperlinkUpdate
(
HyperlinkEvent
e
)
{
Object
obj
=
e
.
getSource
();
if
(
obj
instanceof
JumpPosition
)
{
contentPanel
.
getTabbedPane
().
codeJump
((
JumpPosition
)
obj
);
}
}
}
jadx-gui/src/main/java/jadx/gui/ui/CodePanel.java
→
jadx-gui/src/main/java/jadx/gui/ui/
codearea/
CodePanel.java
View file @
a3464d71
package
jadx
.
gui
.
ui
;
package
jadx
.
gui
.
ui
.
codearea
;
import
javax.swing.*
;
import
java.awt.*
;
...
...
@@ -7,9 +7,11 @@ import java.awt.event.InputEvent;
import
java.awt.event.KeyEvent
;
import
jadx.gui.treemodel.JNode
;
import
jadx.gui.ui.ContentPanel
;
import
jadx.gui.ui.TabbedPane
;
import
jadx.gui.utils.Utils
;
class
CodePanel
extends
ContentPanel
{
public
final
class
CodePanel
extends
ContentPanel
{
private
static
final
long
serialVersionUID
=
5310536092010045565L
;
...
...
@@ -17,7 +19,7 @@ class CodePanel extends ContentPanel {
private
final
CodeArea
codeArea
;
private
final
JScrollPane
scrollPane
;
CodePanel
(
TabbedPane
panel
,
JNode
jnode
)
{
public
CodePanel
(
TabbedPane
panel
,
JNode
jnode
)
{
super
(
panel
,
jnode
);
codeArea
=
new
CodeArea
(
this
);
...
...
@@ -55,12 +57,12 @@ class CodePanel extends ContentPanel {
}
@Override
TabbedPane
getTabbedPane
()
{
public
TabbedPane
getTabbedPane
()
{
return
tabbedPane
;
}
@Override
JNode
getNode
()
{
public
JNode
getNode
()
{
return
node
;
}
...
...
@@ -68,7 +70,7 @@ class CodePanel extends ContentPanel {
return
searchBar
;
}
CodeArea
getCodeArea
()
{
public
CodeArea
getCodeArea
()
{
return
codeArea
;
}
...
...
jadx-gui/src/main/java/jadx/gui/ui/codearea/EditorTheme.java
0 → 100644
View file @
a3464d71
package
jadx
.
gui
.
ui
.
codearea
;
public
final
class
EditorTheme
{
private
static
final
String
RSTA_THEME_PATH
=
"/org/fife/ui/rsyntaxtextarea/themes/"
;
public
static
final
EditorTheme
[]
ALL_THEMES
=
new
EditorTheme
[]{
new
EditorTheme
(
"default"
),
new
EditorTheme
(
"eclipse"
),
new
EditorTheme
(
"idea"
),
new
EditorTheme
(
"vs"
),
new
EditorTheme
(
"dark"
),
new
EditorTheme
(
"monokai"
)
};
private
final
String
name
;
private
final
String
path
;
public
EditorTheme
(
String
name
)
{
this
(
name
,
RSTA_THEME_PATH
+
name
+
".xml"
);
}
public
EditorTheme
(
String
name
,
String
path
)
{
this
.
name
=
name
;
this
.
path
=
path
;
}
public
String
getName
()
{
return
name
;
}
public
String
getPath
()
{
return
path
;
}
@Override
public
String
toString
()
{
return
name
;
}
}
jadx-gui/src/main/java/jadx/gui/ui/codearea/FindUsageAction.java
0 → 100644
View file @
a3464d71
package
jadx
.
gui
.
ui
.
codearea
;
import
javax.swing.*
;
import
javax.swing.event.PopupMenuEvent
;
import
javax.swing.event.PopupMenuListener
;
import
java.awt.*
;
import
java.awt.event.ActionEvent
;
import
org.fife.ui.rsyntaxtextarea.Token
;
import
jadx.api.JavaNode
;
import
jadx.gui.treemodel.JClass
;
import
jadx.gui.treemodel.JNode
;
import
jadx.gui.ui.MainWindow
;
import
jadx.gui.ui.UsageDialog
;
import
jadx.gui.utils.NLS
;
public
final
class
FindUsageAction
extends
AbstractAction
implements
PopupMenuListener
{
private
static
final
long
serialVersionUID
=
4692546569977976384L
;
private
final
transient
CodePanel
contentPanel
;
private
final
transient
CodeArea
codeArea
;
private
final
transient
JClass
jCls
;
private
transient
JavaNode
node
;
public
FindUsageAction
(
CodePanel
contentPanel
,
CodeArea
codeArea
,
JClass
jCls
)
{
super
(
NLS
.
str
(
"popup.find_usage"
));
this
.
contentPanel
=
contentPanel
;
this
.
codeArea
=
codeArea
;
this
.
jCls
=
jCls
;
}
@Override
public
void
actionPerformed
(
ActionEvent
e
)
{
if
(
node
==
null
)
{
return
;
}
MainWindow
mainWindow
=
contentPanel
.
getTabbedPane
().
getMainWindow
();
JNode
jNode
=
mainWindow
.
getCacheObject
().
getNodeCache
().
makeFrom
(
node
);
UsageDialog
usageDialog
=
new
UsageDialog
(
mainWindow
,
jNode
);
usageDialog
.
setVisible
(
true
);
}
@Override
public
void
popupMenuWillBecomeVisible
(
PopupMenuEvent
e
)
{
node
=
null
;
Point
pos
=
codeArea
.
getMousePosition
();
if
(
pos
!=
null
)
{
Token
token
=
codeArea
.
viewToToken
(
pos
);
if
(
token
!=
null
)
{
node
=
codeArea
.
getJavaNodeAtOffset
(
jCls
,
token
.
getOffset
());
}
}
setEnabled
(
node
!=
null
);
}
@Override
public
void
popupMenuWillBecomeInvisible
(
PopupMenuEvent
e
)
{
// do nothing
}
@Override
public
void
popupMenuCanceled
(
PopupMenuEvent
e
)
{
// do nothing
}
}
jadx-gui/src/main/java/jadx/gui/ui/codearea/JadxTokenMaker.java
0 → 100644
View file @
a3464d71
package
jadx
.
gui
.
ui
.
codearea
;
import
javax.swing.text.Segment
;
import
org.fife.ui.rsyntaxtextarea.Token
;
import
org.fife.ui.rsyntaxtextarea.TokenImpl
;
import
org.fife.ui.rsyntaxtextarea.TokenTypes
;
import
org.fife.ui.rsyntaxtextarea.modes.JavaTokenMaker
;
import
org.jetbrains.annotations.NotNull
;
import
org.jetbrains.annotations.Nullable
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
jadx.api.JavaClass
;
import
jadx.api.JavaNode
;
import
jadx.gui.treemodel.JClass
;
public
final
class
JadxTokenMaker
extends
JavaTokenMaker
{
private
static
final
Logger
LOG
=
LoggerFactory
.
getLogger
(
JadxTokenMaker
.
class
);
private
final
CodeArea
codeArea
;
private
final
JClass
jCls
;
public
JadxTokenMaker
(
CodeArea
codeArea
,
JClass
jCls
)
{
this
.
codeArea
=
codeArea
;
this
.
jCls
=
jCls
;
}
@Override
public
Token
getTokenList
(
Segment
text
,
int
initialTokenType
,
int
startOffset
)
{
Token
tokens
=
super
.
getTokenList
(
text
,
initialTokenType
,
startOffset
);
if
(
startOffset
>
0
&&
tokens
.
getType
()
!=
TokenTypes
.
NULL
)
{
try
{
processTokens
(
tokens
);
}
catch
(
Exception
e
)
{
LOG
.
error
(
"Process tokens failed for text: {}"
,
text
,
e
);
}
}
return
tokens
;
}
private
void
processTokens
(
Token
tokens
)
{
Token
prev
=
null
;
Token
current
=
tokens
;
while
(
current
!=
null
)
{
if
(
prev
!=
null
)
{
int
tokenType
=
current
.
getType
();
if
(
tokenType
==
TokenTypes
.
IDENTIFIER
)
{
current
=
mergeLongClassNames
(
prev
,
current
,
false
);
}
else
if
(
tokenType
==
TokenTypes
.
ANNOTATION
)
{
current
=
mergeLongClassNames
(
prev
,
current
,
true
);
}
}
prev
=
current
;
current
=
current
.
getNextToken
();
}
}
@NotNull
private
Token
mergeLongClassNames
(
Token
prev
,
Token
current
,
boolean
annotation
)
{
int
offset
=
current
.
getOffset
();
if
(
annotation
)
{
offset
++;
}
JavaNode
javaNode
=
codeArea
.
getJavaNodeAtOffset
(
jCls
,
offset
);
if
(
javaNode
instanceof
JavaClass
)
{
String
name
=
javaNode
.
getName
();
String
lexeme
=
current
.
getLexeme
();
if
(
annotation
&&
lexeme
.
length
()
>
1
)
{
lexeme
=
lexeme
.
substring
(
1
);
}
if
(!
lexeme
.
equals
(
name
)
&&
javaNode
.
getFullName
().
startsWith
(
lexeme
))
{
// try to replace long class name with one token
Token
replace
=
concatTokensUntil
(
current
,
name
);
if
(
replace
!=
null
&&
prev
instanceof
TokenImpl
)
{
TokenImpl
impl
=
((
TokenImpl
)
prev
);
impl
.
setNextToken
(
replace
);
current
=
replace
;
}
}
}
return
current
;
}
@Nullable
private
Token
concatTokensUntil
(
Token
start
,
String
endText
)
{
StringBuilder
sb
=
new
StringBuilder
();
Token
current
=
start
;
while
(
current
!=
null
&&
current
.
getType
()
!=
TokenTypes
.
NULL
)
{
String
text
=
current
.
getLexeme
();
if
(
text
!=
null
)
{
sb
.
append
(
text
);
if
(
text
.
equals
(
endText
))
{
char
[]
line
=
sb
.
toString
().
toCharArray
();
TokenImpl
token
=
new
TokenImpl
(
line
,
0
,
line
.
length
-
1
,
start
.
getOffset
(),
start
.
getType
(),
start
.
getLanguageIndex
());
token
.
setNextToken
(
current
.
getNextToken
());
return
token
;
}
}
current
=
current
.
getNextToken
();
}
return
null
;
}
}
jadx-gui/src/main/java/jadx/gui/ui/LineNumbers.java
→
jadx-gui/src/main/java/jadx/gui/ui/
codearea/
LineNumbers.java
View file @
a3464d71
package
jadx
.
gui
.
ui
;
package
jadx
.
gui
.
ui
.
codearea
;
import
javax.swing.*
;
import
javax.swing.border.Border
;
...
...
jadx-gui/src/main/java/jadx/gui/ui/SearchBar.java
→
jadx-gui/src/main/java/jadx/gui/ui/
codearea/
SearchBar.java
View file @
a3464d71
package
jadx
.
gui
.
ui
;
package
jadx
.
gui
.
ui
.
codearea
;
import
javax.swing.*
;
import
javax.swing.text.BadLocationException
;
...
...
@@ -112,12 +112,7 @@ class SearchBar extends JToolBar {
JButton
closeButton
=
new
JButton
();
closeButton
.
setIcon
(
ICON_CLOSE
);
closeButton
.
addActionListener
(
new
ActionListener
()
{
@Override
public
void
actionPerformed
(
ActionEvent
e
)
{
toggle
();
}
});
closeButton
.
addActionListener
(
l
->
toggle
());
closeButton
.
setBorderPainted
(
false
);
add
(
closeButton
);
...
...
jadx-gui/src/main/java/jadx/gui/utils/JumpManager.java
View file @
a3464d71
...
...
@@ -5,10 +5,10 @@ import java.util.List;
public
class
JumpManager
{
private
List
<
Position
>
list
=
new
ArrayList
<>();
private
List
<
Jump
Position
>
list
=
new
ArrayList
<>();
private
int
currentPos
=
0
;
public
void
addPosition
(
Position
pos
)
{
public
void
addPosition
(
Jump
Position
pos
)
{
if
(
pos
.
equals
(
getCurrent
()))
{
return
;
}
...
...
@@ -25,14 +25,14 @@ public class JumpManager {
}
}
private
Position
getCurrent
()
{
private
Jump
Position
getCurrent
()
{
if
(
currentPos
>=
0
&&
currentPos
<
list
.
size
())
{
return
list
.
get
(
currentPos
);
}
return
null
;
}
public
Position
getPrev
()
{
public
Jump
Position
getPrev
()
{
if
(
currentPos
==
0
)
{
return
null
;
}
...
...
@@ -40,7 +40,7 @@ public class JumpManager {
return
list
.
get
(
currentPos
);
}
public
Position
getNext
()
{
public
Jump
Position
getNext
()
{
int
size
=
list
.
size
();
if
(
size
==
0
)
{
currentPos
=
0
;
...
...
@@ -51,7 +51,7 @@ public class JumpManager {
currentPos
=
size
-
1
;
return
null
;
}
Position
position
=
list
.
get
(
newPos
);
Jump
Position
position
=
list
.
get
(
newPos
);
if
(
position
==
null
)
{
return
null
;
}
...
...
jadx-gui/src/main/java/jadx/gui/utils/Position.java
→
jadx-gui/src/main/java/jadx/gui/utils/
Jump
Position.java
View file @
a3464d71
package
jadx
.
gui
.
utils
;
import
jadx.api.CodePosition
;
import
jadx.gui.treemodel.JClass
;
import
jadx.gui.treemodel.JNode
;
public
class
Position
{
public
class
Jump
Position
{
private
final
JNode
node
;
private
final
int
line
;
public
Position
(
CodePosition
pos
)
{
this
.
node
=
new
JClass
(
pos
.
getJavaClass
());
this
.
line
=
pos
.
getLine
();
}
public
Position
(
JNode
node
,
int
line
)
{
public
JumpPosition
(
JNode
node
,
int
line
)
{
this
.
node
=
node
;
this
.
line
=
line
;
}
...
...
@@ -31,10 +24,10 @@ public class Position {
if
(
this
==
obj
)
{
return
true
;
}
if
(!(
obj
instanceof
Position
))
{
if
(!(
obj
instanceof
Jump
Position
))
{
return
false
;
}
Position
position
=
(
Position
)
obj
;
JumpPosition
position
=
(
Jump
Position
)
obj
;
return
line
==
position
.
line
&&
node
.
equals
(
position
.
node
);
}
...
...
jadx-gui/src/main/resources/i18n/Messages_en_US.properties
View file @
a3464d71
...
...
@@ -114,6 +114,7 @@ popup.paste=Paste
popup.delete
=
Delete
popup.select_all
=
Select All
popup.find_usage
=
Find Usage
certificate.title
=
Certificate
certificate.cert_type
=
Type
certificate.serialSigVer
=
Version
...
...
jadx-gui/src/test/groovy/jadx/gui/tests/TestJumpManager.groovy
View file @
a3464d71
package
jadx.gui.tests
import
jadx.gui.utils.JumpManager
import
jadx.gui.utils.Position
import
jadx.gui.utils.
Jump
Position
import
spock.lang.Specification
class
TestJumpManager
extends
Specification
{
...
...
@@ -29,7 +29,7 @@ class TestJumpManager extends Specification {
def
"1 element"
()
{
when:
jm
.
addPosition
(
Mock
(
Position
))
jm
.
addPosition
(
Mock
(
Jump
Position
))
then:
jm
.
getPrev
()
==
null
jm
.
getNext
()
==
null
...
...
@@ -37,9 +37,9 @@ class TestJumpManager extends Specification {
def
"2 elements"
()
{
when:
def
mock1
=
Mock
(
Position
)
def
mock1
=
Mock
(
Jump
Position
)
jm
.
addPosition
(
mock1
)
def
mock2
=
Mock
(
Position
)
def
mock2
=
Mock
(
Jump
Position
)
jm
.
addPosition
(
mock2
)
// 1 - 2@
then:
...
...
@@ -52,15 +52,15 @@ class TestJumpManager extends Specification {
def
"navigation"
()
{
expect:
def
mock1
=
Mock
(
Position
)
def
mock1
=
Mock
(
Jump
Position
)
jm
.
addPosition
(
mock1
)
// 1@
def
mock2
=
Mock
(
Position
)
def
mock2
=
Mock
(
Jump
Position
)
jm
.
addPosition
(
mock2
)
// 1 - 2@
jm
.
getPrev
()
==
mock1
// 1@ - 2
def
mock3
=
Mock
(
Position
)
def
mock3
=
Mock
(
Jump
Position
)
jm
.
addPosition
(
mock3
)
// 1 - 3@
jm
.
getNext
()
==
null
...
...
@@ -71,23 +71,23 @@ class TestJumpManager extends Specification {
def
"navigation2"
()
{
expect:
def
mock1
=
Mock
(
Position
)
def
mock1
=
Mock
(
Jump
Position
)
jm
.
addPosition
(
mock1
)
// 1@
def
mock2
=
Mock
(
Position
)
def
mock2
=
Mock
(
Jump
Position
)
jm
.
addPosition
(
mock2
)
// 1 - 2@
def
mock3
=
Mock
(
Position
)
def
mock3
=
Mock
(
Jump
Position
)
jm
.
addPosition
(
mock3
)
// 1 - 2 - 3@
def
mock4
=
Mock
(
Position
)
def
mock4
=
Mock
(
Jump
Position
)
jm
.
addPosition
(
mock4
)
// 1 - 2 - 3 - 4@
jm
.
getPrev
()
==
mock3
// 1 - 2 - 3@ - 4
jm
.
getPrev
()
==
mock2
// 1 - 2@ - 3 - 4
def
mock5
=
Mock
(
Position
)
def
mock5
=
Mock
(
Jump
Position
)
jm
.
addPosition
(
mock5
)
// 1 - 2 - 5@
jm
.
getNext
()
==
null
...
...
@@ -106,7 +106,7 @@ class TestJumpManager extends Specification {
def
"add same element"
()
{
when:
def
mock
=
Mock
(
Position
)
def
mock
=
Mock
(
Jump
Position
)
jm
.
addPosition
(
mock
)
jm
.
addPosition
(
mock
)
then:
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment