mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-09-25 01:30:44 +00:00
Added: AS1/2 - underline errors in the code (also in edit mode)
This commit is contained in:
@@ -19,18 +19,25 @@ package com.jpexs.decompiler.flash.gui.action;
|
||||
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.WavyUnderLinePainter;
|
||||
import java.awt.Color;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseMotionAdapter;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.logging.Logger;
|
||||
import javax.swing.JEditorPane;
|
||||
import javax.swing.event.CaretEvent;
|
||||
@@ -54,16 +61,26 @@ public class ActionVariableMarker implements SyntaxComponent, CaretListener, Pro
|
||||
|
||||
public static final String DEFAULT_TOKENTYPES = "IDENTIFIER, KEYWORD, REGEX";
|
||||
public static final String PROPERTY_COLOR = "ActionVariableMarker.Color";
|
||||
public static final String PROPERTY_ERRORCOLOR = "ActionVariableMarker.ErrorColor";
|
||||
public static final String PROPERTY_TOKENTYPES = "ActionVariableMarker.TokenTypes";
|
||||
private static final Color DEFAULT_COLOR = new Color(0xf8e7d6);
|
||||
private static final Color DEFAULT_COLOR = new Color(0xffeedd);
|
||||
private static final Color DEFAULT_ERRORCOLOR = new Color(0xffaaaa);
|
||||
private JEditorPane pane;
|
||||
private final Set<TokenType> tokenTypes = new HashSet<>();
|
||||
private Markers.SimpleMarker marker;
|
||||
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;
|
||||
|
||||
private Map<Integer, List<Integer>> definitionPosToReferences = new LinkedHashMap<>();
|
||||
private Map<Integer, Integer> referenceToDefinition = new LinkedHashMap<>();
|
||||
|
||||
private MouseMotionAdapter mouseMotionAdapter;
|
||||
|
||||
/**
|
||||
* Constructs a new Token highlighter
|
||||
*/
|
||||
@@ -78,6 +95,12 @@ public class ActionVariableMarker implements SyntaxComponent, CaretListener, Pro
|
||||
public void markTokenAt(int pos) {
|
||||
SyntaxDocument doc = ActionUtils.getSyntaxDocument(pane);
|
||||
if (doc != null) {
|
||||
Token everyToken = getNearestTokenAt(doc, pos);
|
||||
if (everyToken != null) {
|
||||
if (errors.containsKey(everyToken.start)) {
|
||||
//System.err.println(errors.get(everyToken.start));
|
||||
}
|
||||
}
|
||||
Token token = getIdentifierTokenAt(doc, pos);
|
||||
removeMarkers();
|
||||
if (token != null && tokenTypes.contains(token.type)) {
|
||||
@@ -93,6 +116,11 @@ public class ActionVariableMarker implements SyntaxComponent, CaretListener, Pro
|
||||
Markers.removeMarkers(pane, marker);
|
||||
}
|
||||
|
||||
public void removeErrorMarkers() {
|
||||
Markers.removeMarkers(pane, errorMarker);
|
||||
errorsShown = false;
|
||||
}
|
||||
|
||||
private Token getIdentifierTokenAt(SyntaxDocument sDoc, int pos) {
|
||||
Token thisToken = sDoc.getTokenAt(pos);
|
||||
if (thisToken != null && (thisToken.type == TokenType.IDENTIFIER || thisToken.type == TokenType.REGEX || thisToken.type == TokenType.KEYWORD)) {
|
||||
@@ -115,6 +143,42 @@ public class ActionVariableMarker implements SyntaxComponent, CaretListener, Pro
|
||||
return null;
|
||||
}
|
||||
|
||||
private Token getNearestTokenAt(SyntaxDocument sDoc, int pos) {
|
||||
Token thisToken = sDoc.getTokenAt(pos);
|
||||
if (thisToken != null) {
|
||||
return thisToken;
|
||||
}
|
||||
|
||||
Token token = sDoc.getTokenAt(pos - 1);
|
||||
if (token != null
|
||||
&& (token.start + token.length == pos)) {
|
||||
return token;
|
||||
}
|
||||
|
||||
token = sDoc.getTokenAt(pos + 1);
|
||||
if (token != null
|
||||
&& (token.start == pos)) {
|
||||
return token;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
void addErrorMarkers() {
|
||||
SyntaxDocument doc = ActionUtils.getSyntaxDocument(pane);
|
||||
if (doc == null) {
|
||||
return;
|
||||
}
|
||||
doc.readLock();
|
||||
for (int position : errors.keySet()) {
|
||||
Token token = getNearestTokenAt(doc, position);
|
||||
if (token != null) {
|
||||
Markers.markToken(pane, token, errorMarker);
|
||||
}
|
||||
}
|
||||
doc.readUnlock();
|
||||
errorsShown = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* add highlights for the given pattern
|
||||
*
|
||||
@@ -144,9 +208,10 @@ public class ActionVariableMarker implements SyntaxComponent, CaretListener, Pro
|
||||
|
||||
@Override
|
||||
public void config(Configuration config) {
|
||||
Color markerColor = config.getColor(
|
||||
PROPERTY_COLOR, DEFAULT_COLOR);
|
||||
Color markerColor = config.getColor(PROPERTY_COLOR, DEFAULT_COLOR);
|
||||
Color errorColor = config.getColor(PROPERTY_ERRORCOLOR, DEFAULT_ERRORCOLOR);
|
||||
this.marker = new Markers.SimpleMarker(markerColor);
|
||||
this.errorMarker = new WavyUnderLinePainter(Color.red); //Markers.SimpleMarker(errorColor);
|
||||
String types = config.getString(
|
||||
PROPERTY_TOKENTYPES, DEFAULT_TOKENTYPES);
|
||||
|
||||
@@ -173,16 +238,43 @@ public class ActionVariableMarker implements SyntaxComponent, CaretListener, Pro
|
||||
}
|
||||
documentUpdated();
|
||||
markTokenAt(editor.getCaretPosition());
|
||||
mouseMotionAdapter = new MouseMotionAdapter() {
|
||||
@Override
|
||||
public void mouseMoved(MouseEvent e) {
|
||||
editorMouseMoved(e);
|
||||
}
|
||||
};
|
||||
editor.addMouseMotionListener(mouseMotionAdapter);
|
||||
status = Status.INSTALLING;
|
||||
}
|
||||
|
||||
private void editorMouseMoved(MouseEvent e) {
|
||||
if (pane instanceof LineMarkedEditorPane) {
|
||||
Token token = ((LineMarkedEditorPane) pane).getTokenUnderCursor();
|
||||
if (token != null) {
|
||||
String err = errors.get(token.start);
|
||||
pane.setToolTipText(err);
|
||||
} else {
|
||||
pane.setToolTipText(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deinstall(JEditorPane editor) {
|
||||
status = Status.DEINSTALLING;
|
||||
removeMarkers();
|
||||
removeErrorMarkers();
|
||||
Timer tim = errorsTimer;
|
||||
if (tim != null) {
|
||||
tim.cancel();
|
||||
errorsTimer = null;
|
||||
}
|
||||
pane.removePropertyChangeListener(this);
|
||||
pane.getDocument().removeDocumentListener(this);
|
||||
pane.removeCaretListener(this);
|
||||
pane.removeMouseMotionListener(mouseMotionAdapter);
|
||||
mouseMotionAdapter = null;
|
||||
if (editor instanceof LineMarkedEditorPane) {
|
||||
((LineMarkedEditorPane) editor).setLinkHandler(null);
|
||||
}
|
||||
@@ -205,6 +297,8 @@ public class ActionVariableMarker implements SyntaxComponent, CaretListener, Pro
|
||||
}
|
||||
|
||||
private void documentUpdated() {
|
||||
errors.clear();
|
||||
removeErrorMarkers();
|
||||
try {
|
||||
SyntaxDocument sDoc = (SyntaxDocument) pane.getDocument();
|
||||
|
||||
@@ -222,15 +316,37 @@ public class ActionVariableMarker implements SyntaxComponent, CaretListener, Pro
|
||||
Map<Integer, List<Integer>> newDefinitionPosToReferences = new LinkedHashMap<>();
|
||||
Map<Integer, Integer> newReferenceToDefinition = new LinkedHashMap<>();
|
||||
ActionScript2VariableParser varParser = new ActionScript2VariableParser(swf);
|
||||
varParser.parse(fullText, newDefinitionPosToReferences, newReferenceToDefinition);
|
||||
List<ActionVariableParseException> newErrors = new ArrayList<>();
|
||||
varParser.parse(fullText, newDefinitionPosToReferences, newReferenceToDefinition, newErrors);
|
||||
definitionPosToReferences = newDefinitionPosToReferences;
|
||||
referenceToDefinition = newReferenceToDefinition;
|
||||
markTokenAt(pane.getCaretPosition());
|
||||
} catch (BadLocationException | ActionParseException | IOException | InterruptedException ex) {
|
||||
for (ActionVariableParseException ex : newErrors) {
|
||||
errors.put((int) ex.position, ex.getMessage());
|
||||
}
|
||||
} catch (BadLocationException | IOException | InterruptedException ex) {
|
||||
definitionPosToReferences.clear();
|
||||
referenceToDefinition.clear();
|
||||
//ex.printStackTrace();
|
||||
} catch (ActionParseException ex) {
|
||||
definitionPosToReferences.clear();
|
||||
referenceToDefinition.clear();
|
||||
errors.put((int) ex.position, ex.getMessage());
|
||||
}
|
||||
Timer tim = errorsTimer;
|
||||
if (tim != null) {
|
||||
tim.cancel();
|
||||
errorsTimer = null;
|
||||
}
|
||||
tim = new Timer();
|
||||
tim.schedule(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
removeErrorMarkers();
|
||||
addErrorMarkers();
|
||||
}
|
||||
}, ERROR_DELAY);
|
||||
errorsTimer = tim;
|
||||
markTokenAt(pane.getCaretPosition());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -78,6 +78,8 @@ public class LineMarkedEditorPane extends UndoFixedEditorPane implements LinkHan
|
||||
private static final HighlightPainter underLinePainter = new UnderLinePainter(new Color(0, 0, 255));
|
||||
|
||||
private LinkHandler linkHandler = this;
|
||||
|
||||
private Point lastCursorPos = new Point(0, 0);
|
||||
|
||||
public static class LineMarker implements Comparable<LineMarker> {
|
||||
|
||||
@@ -381,11 +383,13 @@ public class LineMarkedEditorPane extends UndoFixedEditorPane implements LinkHan
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Token getTokenUnderCursor() {
|
||||
return tokenAtPos(lastCursorPos);
|
||||
}
|
||||
|
||||
private class LinkAdapter extends MouseAdapter implements KeyListener {
|
||||
|
||||
private Point lastPos = new Point(0, 0);
|
||||
|
||||
|
||||
private boolean ctrlDown = false;
|
||||
|
||||
@Override
|
||||
@@ -411,7 +415,7 @@ public class LineMarkedEditorPane extends UndoFixedEditorPane implements LinkHan
|
||||
|
||||
private void update() {
|
||||
if (ctrlDown) {
|
||||
Token t = tokenAtPos(lastPos);
|
||||
Token t = tokenAtPos(lastCursorPos);
|
||||
|
||||
if (t != lastUnderlined) {
|
||||
if (t == null || lastUnderlined == null || !t.equals(lastUnderlined)) {
|
||||
@@ -446,7 +450,7 @@ public class LineMarkedEditorPane extends UndoFixedEditorPane implements LinkHan
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
if (ctrlDown) {
|
||||
Token t = tokenAtPos(lastPos);
|
||||
Token t = tokenAtPos(lastCursorPos);
|
||||
if (t != null && linkHandler.isLink(t)) {
|
||||
linkHandler.handleLink(t);
|
||||
}
|
||||
@@ -457,7 +461,7 @@ public class LineMarkedEditorPane extends UndoFixedEditorPane implements LinkHan
|
||||
public void mouseMoved(MouseEvent e) {
|
||||
|
||||
ctrlDown = (e.getModifiersEx() & InputEvent.CTRL_DOWN_MASK) != 0;
|
||||
lastPos = e.getPoint();
|
||||
lastCursorPos = e.getPoint();
|
||||
update();
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2025 JPEXS
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* 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.editor;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Shape;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import javax.swing.plaf.TextUI;
|
||||
import javax.swing.text.BadLocationException;
|
||||
import javax.swing.text.JTextComponent;
|
||||
import javax.swing.text.Position;
|
||||
import javax.swing.text.View;
|
||||
import jsyntaxpane.components.Markers;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class WavyUnderLinePainter extends Markers.SimpleMarker {
|
||||
|
||||
public WavyUnderLinePainter(Color color) {
|
||||
super(color);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paint(Graphics g, int offs0, int offs1, Shape bounds, JTextComponent c) {
|
||||
try {
|
||||
// --- determine locations ---
|
||||
TextUI mapper = c.getUI();
|
||||
|
||||
Color col = getColor();
|
||||
if (col == null) {
|
||||
col = Color.black;
|
||||
}
|
||||
g.setColor(col);
|
||||
|
||||
int waveHeight = 2;
|
||||
|
||||
for (int i = offs0; i < offs1; i++) {
|
||||
|
||||
Rectangle2D r = com.jpexs.decompiler.flash.gui.View.textUIModelToView(mapper, c, i, Position.Bias.Forward);
|
||||
Rectangle2D r1 = com.jpexs.decompiler.flash.gui.View.textUIModelToView(mapper, c, i + 1, Position.Bias.Forward);
|
||||
if (r1.getY() == r.getY()) {
|
||||
int x = (int) r.getX();
|
||||
int y = (int) (r.getY() + r1.getHeight());
|
||||
int maxX = (int) r1.getX();
|
||||
boolean up = true;
|
||||
for (; x < maxX; x += 2) {
|
||||
if (up) {
|
||||
g.drawLine(x, y, x + 2, y - waveHeight);
|
||||
} else {
|
||||
g.drawLine(x, y - waveHeight, x + 2, y);
|
||||
}
|
||||
up = !up;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} catch (BadLocationException e) {
|
||||
// can't render
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Shape paintLayer(Graphics g, int offs0, int offs1,
|
||||
Shape bounds, JTextComponent c, View view) {
|
||||
|
||||
g.setColor(c.getSelectionColor());
|
||||
|
||||
Rectangle r;
|
||||
|
||||
if (offs0 == view.getStartOffset()
|
||||
&& offs1 == view.getEndOffset()) {
|
||||
// Contained in view, can just use bounds.
|
||||
if (bounds instanceof Rectangle) {
|
||||
r = (Rectangle) bounds;
|
||||
} else {
|
||||
r = bounds.getBounds();
|
||||
}
|
||||
} else {
|
||||
// Should only render part of View.
|
||||
try {
|
||||
// --- determine locations ---
|
||||
Shape shape = view.modelToView(offs0, Position.Bias.Forward,
|
||||
offs1, Position.Bias.Backward,
|
||||
bounds);
|
||||
r = (shape instanceof Rectangle)
|
||||
? (Rectangle) shape : shape.getBounds();
|
||||
} catch (BadLocationException e) {
|
||||
// can't render
|
||||
r = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (r != null) {
|
||||
r.width = Math.max(r.width, 1);
|
||||
|
||||
paint(g, offs0, offs1, r, c);
|
||||
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user