AS3 highlighter.

Refactoring of highligter.
This commit is contained in:
Jindra Petřík
2025-05-29 09:14:15 +02:00
parent bbeeef4fc5
commit 90d975d69c
23 changed files with 3780 additions and 568 deletions
@@ -27,6 +27,7 @@ import com.jpexs.decompiler.flash.abc.ScriptPack;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instructions;
import com.jpexs.decompiler.flash.abc.avm2.parser.script.ActionScript3SimpleParser;
import com.jpexs.decompiler.flash.abc.types.ABCException;
import com.jpexs.decompiler.flash.abc.types.MethodBody;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
@@ -65,6 +66,7 @@ import com.jpexs.decompiler.flash.gui.View;
import com.jpexs.decompiler.flash.gui.ViewMessages;
import com.jpexs.decompiler.flash.gui.controls.JPersistentSplitPane;
import com.jpexs.decompiler.flash.gui.editor.LinkHandler;
import com.jpexs.decompiler.flash.gui.editor.VariableMarker;
import com.jpexs.decompiler.flash.gui.tagtree.AbstractTagTree;
import com.jpexs.decompiler.flash.gui.tagtree.AbstractTagTreeModel;
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
@@ -140,6 +142,7 @@ import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;
import javax.swing.text.Highlighter;
import javax.swing.tree.TreePath;
import jsyntaxpane.DefaultSyntaxKit;
import jsyntaxpane.Token;
import jsyntaxpane.TokenType;
@@ -249,6 +252,7 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<Scr
libraryComboBox.setSelectedIndex(SWF.LIBRARY_FLASH);
}
this.abc = abc;
decompiledTextArea.setParser(new ActionScript3SimpleParser(abc));
setDecompiledEditMode(false);
navigator.setAbc(abc);
updateLinksLabel();
@@ -993,8 +997,8 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<Scr
popupMenu.add(simplifyExpressionsMenuItem);
//popupMenu.add(removeObfuscatedDeclarationsMenuItem);
return popupMenu;
}
return popupMenu;
}
};
deobfuscateOptionsButton.setToolTipText(AppStrings.translate("button.deobfuscate_options"));
deobfuscateOptionsButton.setMargin(new Insets(0, 0, 0, 0));
@@ -1021,7 +1025,7 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<Scr
JPanel libraryAndLinkPanel = new JPanel(new FlowLayout());
JToggleButton linkButton = new JToggleButton(View.getIcon("link16"));
LinkDialog linkDialog = new LinkDialog(mainPanel, linkButton);
libraryComboBox = new JComboBox<>();
@@ -1047,8 +1051,8 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<Scr
libraryAndLinkPanel.add(linksLabel);
linkButton.setToolTipText(AppStrings.translate("button.abc.linkedSwfs.hint"));
linkButton.setToolTipText(AppStrings.translate("button.abc.linkedSwfs.hint"));
linkDialog.addSaveListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
@@ -1153,6 +1157,8 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<Scr
//decLabel.setBorder(new BevelBorder(BevelBorder.RAISED));
decompiledTextArea.changeContentType("text/actionscript3");
DefaultSyntaxKit kit = (DefaultSyntaxKit) decompiledTextArea.getEditorKit();
kit.installComponent(decompiledTextArea, VariableMarker.class.getName());
decompiledTextArea.setFont(Configuration.getSourceFont());
View.addEditorAction(decompiledTextArea, new AbstractAction() {
@@ -1757,7 +1763,7 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<Scr
TreeItem sel = mainPanel.getCurrentTree().getCurrentTreeItem();
if ((sel instanceof ScriptPack) && (sel != pack)) {
mainPanel.replaceItemPin(pack, sel);
}
}
}
reload();
mainPanel.clearEditingStatus();
@@ -1819,7 +1825,7 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<Scr
} else {
toggleButton.setSelected(Configuration.autoDeobfuscate.get());
}
}
}
private void simplifyExpressionsMenuItemActionPerformed(ActionEvent evt) {
JCheckBoxMenuItem menuItem = (JCheckBoxMenuItem) evt.getSource();
@@ -2110,13 +2116,13 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<Scr
flexLabel.setVisible(useFlex && !value);
editDecompiledButton.setEnabled(!value);
}
public void setScript(ScriptPack scriptPack) {
setDecompiledEditMode(false);
detailPanel.setEditMode(false);
detailPanel.setEditMode(false);
detailPanel.methodTraitPanel.methodCodePanel.clear();
decompiledTextArea.setNoTrait();
decompiledTextArea.setNoTrait();
setAbc(scriptPack.abc);
decompiledTextArea.setScript(scriptPack, true);
decompiledTextArea.setScript(scriptPack, true);
}
}
@@ -60,8 +60,6 @@ import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import jsyntaxpane.SyntaxDocument;
import jsyntaxpane.Token;
import jsyntaxpane.TokenType;
@@ -101,8 +99,8 @@ public class DecompiledEditorPane extends DebuggableEditorPane implements CaretL
public synchronized boolean isScriptLoaded() {
return scriptLoaded;
}
}
public void addScriptListener(Runnable l) {
scriptListeners.add(l);
}
@@ -882,18 +880,17 @@ public class DecompiledEditorPane extends DebuggableEditorPane implements CaretL
public void setScript(ScriptPack scriptLeaf, boolean force) {
View.checkAccess();
if (setSourceWorker != null) {
setSourceWorker.cancel(true);
setSourceWorker = null;
}
synchronized (this) {
scriptLoaded = false;
}
if (!force && this.script == scriptLeaf) {
if (!force && this.script == scriptLeaf) {
synchronized (this) {
scriptLoaded = true;
}
@@ -1004,8 +1001,6 @@ public class DecompiledEditorPane extends DebuggableEditorPane implements CaretL
abcPanel.brokenHintPanel.setVisible(false);
}
setText(hilightedCode);
if (highlightedText.getClassHighlights().size() > 0) {
try {
@@ -1018,7 +1013,7 @@ public class DecompiledEditorPane extends DebuggableEditorPane implements CaretL
}
}
scriptLoaded = true;
scriptLoaded = true;
fireScript();
}
@@ -1079,9 +1074,9 @@ public class DecompiledEditorPane extends DebuggableEditorPane implements CaretL
}
setCaretPosition(position);
}
@Override
public synchronized void setCaretPosition(int position) {
super.setCaretPosition(position);
}
}
}
@@ -16,9 +16,11 @@
*/
package com.jpexs.decompiler.flash.gui.action;
import com.jpexs.decompiler.flash.gui.editor.VariableMarker;
import com.jpexs.decompiler.flash.DisassemblyListener;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.ValueTooLargeException;
import com.jpexs.decompiler.flash.abc.avm2.parser.script.ActionScript3SimpleParser;
import com.jpexs.decompiler.flash.action.Action;
import com.jpexs.decompiler.flash.action.ActionGraph;
import com.jpexs.decompiler.flash.action.ActionList;
@@ -29,6 +31,7 @@ import com.jpexs.decompiler.flash.action.parser.pcode.ASMParsedSymbol;
import com.jpexs.decompiler.flash.action.parser.pcode.ASMParser;
import com.jpexs.decompiler.flash.action.parser.pcode.FlasmLexer;
import com.jpexs.decompiler.flash.action.parser.script.ActionScript2Parser;
import com.jpexs.decompiler.flash.action.parser.script.ActionScript2SimpleParser;
import com.jpexs.decompiler.flash.action.parser.script.ActionScriptLexer;
import com.jpexs.decompiler.flash.action.parser.script.ParsedSymbol;
import com.jpexs.decompiler.flash.action.parser.script.SymbolType;
@@ -637,7 +640,7 @@ public class ActionPanel extends JPanel implements SearchListener<ScriptSearchRe
editor.setShowMarkers(true);
decompiledEditor.setShowMarkers(Configuration.decompile.get());
decompiledEditor.setSwf(asm.getSwf());
decompiledEditor.setParser(new ActionScript2SimpleParser(asm.getSwf()));
lastASM = asm;
lastCode = actions;
lastDecompiled = decompiledText;
@@ -1033,7 +1036,7 @@ public class ActionPanel extends JPanel implements SearchListener<ScriptSearchRe
decompiledEditor.setFont(Configuration.getSourceFont());
decompiledEditor.changeContentType("text/actionscript");
DefaultSyntaxKit kit = (DefaultSyntaxKit) decompiledEditor.getEditorKit();
kit.installComponent(decompiledEditor, ActionVariableMarker.class.getName());
kit.installComponent(decompiledEditor, VariableMarker.class.getName());
editor.addCaretListener(new CaretListener() {
@Override
@@ -80,7 +80,6 @@ public class DebuggableEditorPane extends LineMarkedEditorPane implements BreakP
private boolean showMarkers = true;
private WeakReference<SWF> swfRef = new WeakReference(null);
public DebuggableEditorPane() {
@@ -91,14 +90,6 @@ public class DebuggableEditorPane extends LineMarkedEditorPane implements BreakP
BREAKPOINT_MARKER = new LineMarker(FG_BREAKPOINT_COLOR, BG_BREAKPOINT_COLOR, PRIORITY_BREAKPOINT);
}
}
public void setSwf(SWF swf) {
this.swfRef = new WeakReference<>(swf);
}
public SWF getSwf() {
return swfRef.get();
}
public synchronized void setScriptName(String scriptName, String breakPointScriptName) {
this.scriptName = scriptName;
@@ -18,6 +18,7 @@ package com.jpexs.decompiler.flash.gui.editor;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.gui.AppStrings;
import com.jpexs.decompiler.flash.simpleparser.SimpleParser;
import com.jpexs.helpers.Reference;
import java.awt.Color;
import java.awt.Cursor;
@@ -80,7 +81,9 @@ public class LineMarkedEditorPane extends UndoFixedEditorPane implements LinkHan
private LinkHandler linkHandler = this;
private Point lastCursorPos = new Point(0, 0);
private SimpleParser parser;
public static class LineMarker implements Comparable<LineMarker> {
private final Color bgColor;
@@ -147,6 +150,15 @@ public class LineMarkedEditorPane extends UndoFixedEditorPane implements LinkHan
}
}
public SimpleParser getParser() {
return parser;
}
public void setParser(SimpleParser parser) {
this.parser = parser;
}
private Map<Integer, SortedSet<LineMarker>> lineMarkers = Collections.synchronizedMap(new HashMap<Integer, SortedSet<LineMarker>>());
public void setLineMarkers(Map<Integer, SortedSet<LineMarker>> colorMarkers) {
@@ -14,18 +14,10 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.gui.action;
package com.jpexs.decompiler.flash.gui.editor;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.action.parser.ActionParseException;
import com.jpexs.decompiler.flash.action.parser.script.variables.ActionScript2VariableParser;
import com.jpexs.decompiler.flash.action.parser.script.variables.ActionVariableParseException;
import com.jpexs.decompiler.flash.gui.editor.DebuggableEditorPane;
import com.jpexs.decompiler.flash.gui.editor.LineMarkedEditorPane;
import com.jpexs.decompiler.flash.gui.editor.LinkHandler;
import com.jpexs.decompiler.flash.gui.editor.ScrollbarOverlay;
import com.jpexs.decompiler.flash.gui.editor.TrackRectSubstanceScrollbarUI;
import com.jpexs.decompiler.flash.gui.editor.WavyUnderLinePainter;
import com.jpexs.decompiler.flash.simpleparser.SimpleParseException;
import com.jpexs.decompiler.flash.simpleparser.SimpleParser;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.MouseEvent;
@@ -41,7 +33,6 @@ import java.util.Map;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JEditorPane;
import javax.swing.JLayer;
@@ -69,9 +60,9 @@ import jsyntaxpane.util.Configuration;
import org.pushingpixels.substance.internal.ui.SubstanceScrollBarUI;
/**
* This class highlights Variable tokens of ActionScript 1/2
* This class highlights Variable and error tokens.
*/
public class ActionVariableMarker implements SyntaxComponent, CaretListener, PropertyChangeListener, DocumentListener, LinkHandler {
public class VariableMarker implements SyntaxComponent, CaretListener, PropertyChangeListener, DocumentListener, LinkHandler {
public static final String DEFAULT_TOKENTYPES = "IDENTIFIER, KEYWORD, REGEX";
public static final String PROPERTY_COLOR = "ActionVariableMarker.Color";
@@ -88,8 +79,6 @@ public class ActionVariableMarker implements SyntaxComponent, CaretListener, Pro
private Markers.SimpleMarker errorMarker;
private Status status;
private Map<Integer, String> errors = new LinkedHashMap<>();
private boolean errorsShown = false;
public static final long ERROR_DELAY = 2000;
private Timer errorsTimer;
@@ -109,7 +98,7 @@ public class ActionVariableMarker implements SyntaxComponent, CaretListener, Pro
/**
* Constructs a new Token highlighter
*/
public ActionVariableMarker() {
public VariableMarker() {
}
@Override
@@ -145,7 +134,6 @@ public class ActionVariableMarker implements SyntaxComponent, CaretListener, Pro
public void removeErrorMarkers() {
Markers.removeMarkers(pane, errorMarker);
errorsShown = false;
scrollbarOverlay.removeMarkers(SCROLLBAR_ERROR_COLOR);
}
@@ -206,7 +194,6 @@ public class ActionVariableMarker implements SyntaxComponent, CaretListener, Pro
}
layer.repaint();
doc.readUnlock();
errorsShown = true;
}
/**
@@ -348,7 +335,7 @@ public class ActionVariableMarker implements SyntaxComponent, CaretListener, Pro
scrollPane.getVerticalScrollBar().setUI(originalScrollBarUI);
}
private static final Logger LOG = Logger.getLogger(ActionVariableMarker.class.getName());
private static final Logger LOG = Logger.getLogger(VariableMarker.class.getName());
@Override
public void propertyChange(PropertyChangeEvent evt) {
@@ -373,30 +360,28 @@ public class ActionVariableMarker implements SyntaxComponent, CaretListener, Pro
String fullText = sDoc.getText(0, sDoc.getLength());
SWF swf = null;
if (pane instanceof DebuggableEditorPane) {
DebuggableEditorPane dpane = (DebuggableEditorPane) pane;
swf = dpane.getSwf();
if (!(pane instanceof LineMarkedEditorPane)) {
return;
}
if (swf == null) {
SimpleParser parser = ((LineMarkedEditorPane) pane).getParser();
if (parser == null) {
return;
}
Map<Integer, List<Integer>> newDefinitionPosToReferences = new LinkedHashMap<>();
Map<Integer, Integer> newReferenceToDefinition = new LinkedHashMap<>();
ActionScript2VariableParser varParser = new ActionScript2VariableParser(swf);
List<ActionVariableParseException> newErrors = new ArrayList<>();
varParser.parse(fullText, newDefinitionPosToReferences, newReferenceToDefinition, newErrors);
List<SimpleParseException> newErrors = new ArrayList<>();
parser.parse(fullText, newDefinitionPosToReferences, newReferenceToDefinition, newErrors);
definitionPosToReferences = newDefinitionPosToReferences;
referenceToDefinition = newReferenceToDefinition;
for (ActionVariableParseException ex : newErrors) {
for (SimpleParseException ex : newErrors) {
errors.put((int) ex.position, ex.getMessage());
}
} catch (BadLocationException | IOException | InterruptedException ex) {
definitionPosToReferences.clear();
referenceToDefinition.clear();
//ex.printStackTrace();
} catch (ActionParseException ex) {
} catch (SimpleParseException ex) {
definitionPosToReferences.clear();
referenceToDefinition.clear();
errors.put((int) ex.position, ex.getMessage());