mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-05-30 02:50:06 +08:00
Merge remote-tracking branch 'origin/GP-6751-dragonmacher-decompiler-highlights'
This commit is contained in:
+2
-3
@@ -4,9 +4,9 @@
|
||||
* Licensed 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
|
||||
*
|
||||
*
|
||||
* 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.
|
||||
@@ -33,7 +33,6 @@ public class ClangCommentToken extends ClangToken {
|
||||
newToken.setText(text);
|
||||
newToken.setLineParent(source.getLineParent());
|
||||
newToken.setSyntaxType(source.getSyntaxType());
|
||||
newToken.setHighlight(source.getHighlight());
|
||||
newToken.srcaddr = source.srcaddr;
|
||||
return newToken;
|
||||
}
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
* Licensed 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
|
||||
*
|
||||
*
|
||||
* 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.
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package ghidra.app.decompiler;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.util.List;
|
||||
|
||||
import ghidra.program.model.address.Address;
|
||||
@@ -45,12 +44,6 @@ public interface ClangNode {
|
||||
*/
|
||||
public Address getMaxAddress();
|
||||
|
||||
/**
|
||||
* Set a highlighting background color for all text elements
|
||||
* @param c is the color to set
|
||||
*/
|
||||
public void setHighlight(Color c);
|
||||
|
||||
/**
|
||||
* Return the number of immediate groupings this text breaks up into
|
||||
* @return the number of child groupings
|
||||
|
||||
@@ -18,7 +18,6 @@ package ghidra.app.decompiler;
|
||||
import static ghidra.program.model.pcode.AttributeId.*;
|
||||
import static ghidra.program.model.pcode.ElementId.*;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
@@ -49,13 +48,11 @@ public class ClangToken implements ClangNode {
|
||||
private ClangLine lineparent;
|
||||
private String text;
|
||||
private int syntax_type;
|
||||
private Color highlight; // Color to highlight with or null if no highlight
|
||||
private boolean matchingToken;
|
||||
|
||||
public ClangToken(ClangNode par) {
|
||||
parent = par;
|
||||
text = null;
|
||||
highlight = null;
|
||||
syntax_type = DEFAULT_COLOR;
|
||||
lineparent = null;
|
||||
}
|
||||
@@ -63,14 +60,12 @@ public class ClangToken implements ClangNode {
|
||||
public ClangToken(ClangNode par, String txt) {
|
||||
parent = par;
|
||||
text = txt;
|
||||
highlight = null;
|
||||
syntax_type = DEFAULT_COLOR;
|
||||
}
|
||||
|
||||
public ClangToken(ClangNode par, String txt, int color) {
|
||||
parent = par;
|
||||
text = txt;
|
||||
highlight = null;
|
||||
syntax_type = color;
|
||||
}
|
||||
|
||||
@@ -123,19 +118,6 @@ public class ClangToken implements ClangNode {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHighlight(Color val) {
|
||||
highlight = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the background highlight color used to render this token, or null if not highlighted
|
||||
* @return the Color or null
|
||||
*/
|
||||
public Color getHighlight() {
|
||||
return highlight;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether or not additional "matching" highlighting is applied to this token.
|
||||
* Currently this means a bounding box is drawn around the token.
|
||||
|
||||
+3
-13
@@ -4,9 +4,9 @@
|
||||
* Licensed 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
|
||||
*
|
||||
*
|
||||
* 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.
|
||||
@@ -17,7 +17,6 @@ package ghidra.app.decompiler;
|
||||
|
||||
import static ghidra.program.model.pcode.ElementId.*;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.util.*;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@@ -97,13 +96,6 @@ public class ClangTokenGroup implements ClangNode, Iterable<ClangNode> {
|
||||
return parent.getClangFunction();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHighlight(Color val) {
|
||||
for (ClangNode element : tokgroup) {
|
||||
element.setHighlight(val);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flatten(List<ClangNode> list) {
|
||||
for (ClangNode element : tokgroup) {
|
||||
@@ -168,9 +160,7 @@ public class ClangTokenGroup implements ClangNode, Iterable<ClangNode> {
|
||||
public String toString() {
|
||||
String lastTokenStr = null;
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
Iterator<ClangNode> iter = tokgroup.iterator();
|
||||
while (iter.hasNext()) {
|
||||
ClangNode node = iter.next();
|
||||
for (ClangNode node : tokgroup) {
|
||||
String tokenStr = node.toString();
|
||||
if (tokenStr.length() == 0) {
|
||||
continue;
|
||||
|
||||
+10
-7
@@ -4,9 +4,9 @@
|
||||
* Licensed 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
|
||||
*
|
||||
*
|
||||
* 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.
|
||||
@@ -27,9 +27,12 @@ import ghidra.app.decompiler.ClangToken;
|
||||
public class ClangFieldElement extends AbstractTextFieldElement {
|
||||
|
||||
private final ClangToken token;
|
||||
private ClangHighlightController hlController;
|
||||
|
||||
public ClangFieldElement(ClangToken token, AttributedString as, int col) {
|
||||
public ClangFieldElement(ClangHighlightController hlController, ClangToken token,
|
||||
AttributedString as, int col) {
|
||||
super(as, 0, col);
|
||||
this.hlController = hlController;
|
||||
this.token = token;
|
||||
}
|
||||
|
||||
@@ -39,7 +42,7 @@ public class ClangFieldElement extends AbstractTextFieldElement {
|
||||
|
||||
@Override
|
||||
public void paint(JComponent c, Graphics g, int x, int y) {
|
||||
Color highlightColor = token.getHighlight();
|
||||
Color highlightColor = hlController.getCombinedColor(token);
|
||||
if (highlightColor != null) {
|
||||
g.setColor(highlightColor);
|
||||
g.fillRect(x, y - getHeightAbove(), getStringWidth(),
|
||||
@@ -63,12 +66,12 @@ public class ClangFieldElement extends AbstractTextFieldElement {
|
||||
if (as == attributedString) {
|
||||
return this;
|
||||
}
|
||||
return new ClangFieldElement(token, as, column + start);
|
||||
return new ClangFieldElement(hlController, token, as, column + start);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FieldElement replaceAll(char[] targets, char replacement) {
|
||||
return new ClangFieldElement(token, attributedString.replaceAll(targets, replacement),
|
||||
column);
|
||||
AttributedString as = attributedString.replaceAll(targets, replacement);
|
||||
return new ClangFieldElement(hlController, token, as, column);
|
||||
}
|
||||
}
|
||||
|
||||
+7
-34
@@ -30,6 +30,7 @@ import ghidra.program.model.pcode.HighFunction;
|
||||
import ghidra.program.model.pcode.PcodeOp;
|
||||
import ghidra.util.ColorUtils;
|
||||
import util.CollectionUtils;
|
||||
import utility.function.Dummy;
|
||||
|
||||
/**
|
||||
* Class to handle highlights for a decompiled function.
|
||||
@@ -86,7 +87,6 @@ public abstract class ClangHighlightController {
|
||||
|
||||
// arbitrary value chosen by guessing; this can be changed if needed
|
||||
private int maxColorBlendSize = 5;
|
||||
private boolean isRebuilding;
|
||||
|
||||
private List<ClangHighlightListener> listeners = new ArrayList<>();
|
||||
|
||||
@@ -169,33 +169,19 @@ public abstract class ClangHighlightController {
|
||||
// finished. This allows all highlights to calculate their matches without the color
|
||||
// blending affecting performance.
|
||||
//
|
||||
isRebuilding = true;
|
||||
Set<DecompilerHighlighter> service = getServiceHighlighters();
|
||||
Set<DecompilerHighlighter> secondary = getSecondaryHighlighters(function);
|
||||
Iterable<DecompilerHighlighter> it = CollectionUtils.asIterable(service, secondary);
|
||||
|
||||
try {
|
||||
for (DecompilerHighlighter highlighter : it) {
|
||||
highlighter.clearHighlights();
|
||||
highlighter.applyHighlights();
|
||||
}
|
||||
}
|
||||
finally {
|
||||
isRebuilding = false;
|
||||
for (DecompilerHighlighter highlighter : it) {
|
||||
highlighter.clearHighlights();
|
||||
highlighter.applyHighlights();
|
||||
}
|
||||
|
||||
// gather all highlighted tokens and then update their color
|
||||
Set<ClangToken> allTokens = new HashSet<>();
|
||||
it = CollectionUtils.asIterable(service, secondary);
|
||||
for (DecompilerHighlighter highlighter : it) {
|
||||
TokenHighlights hlTokens = userHighlights.add(highlighter);
|
||||
for (HighlightToken hlToken : hlTokens) {
|
||||
allTokens.add(hlToken.getToken());
|
||||
}
|
||||
}
|
||||
|
||||
for (ClangToken token : allTokens) {
|
||||
updateHighlightColor(token);
|
||||
userHighlights.add(highlighter);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -238,7 +224,6 @@ public abstract class ClangHighlightController {
|
||||
public void clearPrimaryHighlights() {
|
||||
Consumer<ClangToken> clearAll = token -> {
|
||||
token.setMatchingToken(false);
|
||||
updateHighlightColor(token);
|
||||
};
|
||||
|
||||
doClearHighlights(contextHighlightTokens, clearAll);
|
||||
@@ -297,7 +282,7 @@ public abstract class ClangHighlightController {
|
||||
|
||||
for (DecompilerHighlighter highlighter : highlighters) {
|
||||
TokenHighlights highlights = userHighlights.getHighlights(highlighter);
|
||||
Consumer<ClangToken> clearHighlight = token -> updateHighlightColor(token);
|
||||
Consumer<ClangToken> clearHighlight = Dummy.consumer();
|
||||
doClearHighlights(highlights, clearHighlight);
|
||||
}
|
||||
highlighters.clear();
|
||||
@@ -333,7 +318,7 @@ public abstract class ClangHighlightController {
|
||||
return;
|
||||
}
|
||||
|
||||
Consumer<ClangToken> clearHighlight = token -> updateHighlightColor(token);
|
||||
Consumer<ClangToken> clearHighlight = Dummy.consumer();
|
||||
doClearHighlights(highlighterTokens, clearHighlight);
|
||||
notifyListeners();
|
||||
}
|
||||
@@ -417,18 +402,6 @@ public abstract class ClangHighlightController {
|
||||
|
||||
// store the actual requested color
|
||||
currentHighlights.add(new HighlightToken(clangToken, highlightColor));
|
||||
updateHighlightColor(clangToken);
|
||||
}
|
||||
|
||||
private void updateHighlightColor(ClangToken t) {
|
||||
|
||||
if (isRebuilding) {
|
||||
return;
|
||||
}
|
||||
|
||||
// set the color to the current combined value of all highlight types
|
||||
Color combinedColor = getCombinedColor(t);
|
||||
t.setHighlight(combinedColor);
|
||||
}
|
||||
|
||||
private void add(Set<Color> colors, HighlightToken hlToken) {
|
||||
|
||||
+3
-2
@@ -183,20 +183,21 @@ public class ClangLayoutController implements LayoutModel, LayoutModelListener {
|
||||
|
||||
FieldElement[] elements = new FieldElement[tokens.size()];
|
||||
int columnPosition = 0;
|
||||
Program program = decompilerPanel.getProgram();
|
||||
ClangHighlightController hlController = decompilerPanel.getHighlightController();
|
||||
for (int i = 0; i < tokens.size(); ++i) {
|
||||
ClangToken token = tokens.get(i);
|
||||
Color color = getTokenColor(token);
|
||||
|
||||
if (token instanceof ClangCommentToken) {
|
||||
AttributedString prototype = new AttributedString("prototype", color, metrics);
|
||||
Program program = decompilerPanel.getProgram();
|
||||
elements[i] =
|
||||
CommentUtils.parseTextForAnnotations(token.getText(), program, prototype, 0);
|
||||
columnPosition += elements[i].length();
|
||||
}
|
||||
else {
|
||||
AttributedString as = new AttributedString(token.getText(), color, metrics);
|
||||
elements[i] = new ClangFieldElement(token, as, columnPosition);
|
||||
elements[i] = new ClangFieldElement(hlController, token, as, columnPosition);
|
||||
columnPosition += as.length();
|
||||
}
|
||||
}
|
||||
|
||||
+16
-9
@@ -2048,7 +2048,7 @@ public class DecompilerClangTest extends AbstractDecompilerTest {
|
||||
private void assertCombinedHighlightColor(ClangToken token) {
|
||||
|
||||
Color combinedColor = getCombinedHighlightColor(token);
|
||||
Color actual = token.getHighlight();
|
||||
Color actual = getHighlight(provider, token);
|
||||
assertEquals(combinedColor, actual);
|
||||
}
|
||||
|
||||
@@ -2139,7 +2139,8 @@ public class DecompilerClangTest extends AbstractDecompilerTest {
|
||||
DecompilerController controller = provider.getController();
|
||||
DecompilerPanel panel = controller.getDecompilerPanel();
|
||||
Color hlColor = panel.getCurrentVariableHighlightColor();
|
||||
assertEquals(hlColor, token.getHighlight());
|
||||
Color actual = getHighlight(provider, token);
|
||||
assertEquals(hlColor, actual);
|
||||
}
|
||||
|
||||
private void rename(String newName) {
|
||||
@@ -2265,7 +2266,7 @@ public class DecompilerClangTest extends AbstractDecompilerTest {
|
||||
// test the token under the cursor directly, as that may have a combined highlight applied
|
||||
Color combinedColor = getCombinedHighlightColor(theProvider, cursorToken);
|
||||
ColorMatcher cm = new ColorMatcher(color, combinedColor);
|
||||
Color actual = cursorToken.getHighlight();
|
||||
Color actual = getHighlight(theProvider, cursorToken);
|
||||
assertTrue("Token is not highlighted: '" + cursorToken + "'" + "\n\texpected: " + cm +
|
||||
"; found: " + toString(actual), cm.matches(actual));
|
||||
}
|
||||
@@ -2283,7 +2284,7 @@ public class DecompilerClangTest extends AbstractDecompilerTest {
|
||||
// test the token under the cursor directly, as that may have a combined highlight applied
|
||||
Color combinedColor = getCombinedHighlightColor(token);
|
||||
ColorMatcher cm = new ColorMatcher(color, combinedColor);
|
||||
Color actual = token.getHighlight();
|
||||
Color actual = getHighlight(provider, token);
|
||||
String tokenString = token.toString() + " at line " + token.getLineParent().getLineNumber();
|
||||
assertTrue("Token is not highlighted: '" + tokenString + "'" + "\n\texpected: " + cm +
|
||||
"; found: " + toString(actual), cm.matches(actual));
|
||||
@@ -2330,7 +2331,7 @@ public class DecompilerClangTest extends AbstractDecompilerTest {
|
||||
continue;
|
||||
}
|
||||
|
||||
Color actual = token.getHighlight();
|
||||
Color actual = getHighlight(provider, token);
|
||||
assertTrue("Token is not highlighted: '" + token + "'" + "\n\texpected: " + cm +
|
||||
"; found: " + toString(actual), cm.matches(actual));
|
||||
}
|
||||
@@ -2357,7 +2358,7 @@ public class DecompilerClangTest extends AbstractDecompilerTest {
|
||||
continue;
|
||||
}
|
||||
|
||||
Color actual = token.getHighlight();
|
||||
Color actual = getHighlight(theProvider, token);
|
||||
assertTrue("Token is not highlighted: '" + token + "'" + "\n\texpected: " + cm +
|
||||
"; found: " + toString(actual), cm.matches(actual));
|
||||
}
|
||||
@@ -2378,7 +2379,7 @@ public class DecompilerClangTest extends AbstractDecompilerTest {
|
||||
assertAllFieldsHighlighted(theProvider, name, cm, ignores);
|
||||
|
||||
// test the token under the cursor directly, as that may have a combined highlight applied
|
||||
Color actual = token.getHighlight();
|
||||
Color actual = getHighlight(theProvider, token);
|
||||
assertTrue("Token is not highlighted: '" + token + "'" + "\n\texpected: " + cm +
|
||||
"; found: " + toString(actual), cm.matches(actual));
|
||||
}
|
||||
@@ -2394,7 +2395,7 @@ public class DecompilerClangTest extends AbstractDecompilerTest {
|
||||
continue;
|
||||
}
|
||||
|
||||
Color actual = otherToken.getHighlight();
|
||||
Color actual = getHighlight(theProvider, otherToken);
|
||||
assertTrue("Token is not highlighted: '" + otherToken + "'" + "\n\texpected: " +
|
||||
colorMatcher + "; found: " + toString(actual), colorMatcher.matches(actual));
|
||||
}
|
||||
@@ -2411,7 +2412,7 @@ public class DecompilerClangTest extends AbstractDecompilerTest {
|
||||
continue;
|
||||
}
|
||||
|
||||
Color actual = otherToken.getHighlight();
|
||||
Color actual = getHighlight(theProvider, otherToken);
|
||||
Color combinedColor = getCombinedHighlightColor(otherToken);
|
||||
ColorMatcher combinedColorMatcher = colorMatcher.with(combinedColor);
|
||||
assertTrue(
|
||||
@@ -2421,6 +2422,12 @@ public class DecompilerClangTest extends AbstractDecompilerTest {
|
||||
}
|
||||
}
|
||||
|
||||
private Color getHighlight(DecompilerProvider theProvider, ClangToken token) {
|
||||
DecompilerPanel panel = theProvider.getController().getDecompilerPanel();
|
||||
ClangHighlightController highlightController = panel.getHighlightController();
|
||||
return highlightController.getCombinedColor(token);
|
||||
}
|
||||
|
||||
private String toString(Color c) {
|
||||
if (c == null) {
|
||||
return "Color{null}";
|
||||
|
||||
Reference in New Issue
Block a user