mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2024-12-11 05:33:19 +00:00
GP-388 Adding feature to simplify the display names in the listing for symbol and datatype names that have complex template info in thier names
This commit is contained in:
parent
1f72861388
commit
8bb02c47df
@ -936,6 +936,33 @@
|
||||
<P><B>Selection Color</B> - Set the Browser <A href=
|
||||
"CodeBrowser.htm#Selection">Selection</A> color.</P>
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<H3><A name="Template_Display_Options"></A>Template Display Options</H3>
|
||||
<BLOCKQUOTE>
|
||||
<P><B>Max Template Depth</B> - Sets the depth to display nested templates. A
|
||||
depth of 0 completely simplifies the entire template, while a depth of 1 will
|
||||
show 1 level of templates.For example, if the name was "foo<char,bar<int, dog<char>>",
|
||||
a nesting depth of 0 would display "foo<>" and an nesting depth of 1 would display
|
||||
"foo<char, bar<>>".
|
||||
</P>
|
||||
|
||||
<P><B>Max Template Length</B> - This is the maximum length any template string will display.
|
||||
If the template string exceeds this length, the middle part of the template will be replaced
|
||||
with "..." to get the string down to the minimum length. For example, the string
|
||||
"foo<abcdefghijklmnopqrstuvwxyz,0123456789>" would display something like "foo<abcd...6789>"
|
||||
if the max length was set to 10. Note that this restriction is applied AFTER
|
||||
any simplifications from the nesting depth.
|
||||
</P>
|
||||
|
||||
<P><B>Min Template Length</B> - This is the minimum length of a template before template
|
||||
simplification is applied. In other words, if the template string is less than this length,
|
||||
then the template will not be simplified. This is done so that simple templates such as
|
||||
"foo<char>" are not simplified to "foo<>", even if the template nesting depth is set to 0.
|
||||
</P>
|
||||
|
||||
<P><B>Simplify Templated Names</B> - This turns the entire templating simplification feature
|
||||
on or off. If this is off, none of the other option have any effect.</P>
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<H3><A name="XREFs_Field"></A>XREFs Field</H3>
|
||||
|
||||
|
@ -20,6 +20,7 @@ import java.util.ArrayList;
|
||||
|
||||
import generic.theme.GThemeDefaults.Colors.Messages;
|
||||
import ghidra.app.util.DisplayableEol;
|
||||
import ghidra.app.util.template.TemplateSimplifier;
|
||||
import ghidra.framework.plugintool.ServiceProvider;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressSetView;
|
||||
@ -85,7 +86,8 @@ class ProgramTextWriter {
|
||||
writer.print("<HTML><BODY BGCOLOR=#ffffe0>");
|
||||
writer.println("<FONT FACE=COURIER SIZE=3><STRONG><PRE>");
|
||||
}
|
||||
|
||||
TemplateSimplifier simplifier = new TemplateSimplifier();
|
||||
simplifier.setEnabled(false);
|
||||
CodeUnitFormatOptions formatOptions = new CodeUnitFormatOptions(
|
||||
options.isShowBlockNameInOperands() ? CodeUnitFormatOptions.ShowBlockName.NON_LOCAL
|
||||
: CodeUnitFormatOptions.ShowBlockName.NEVER,
|
||||
@ -95,7 +97,8 @@ class ProgramTextWriter {
|
||||
true, // include extended reference markup
|
||||
true, // include scalar adjustment
|
||||
true, // include library names in namespace
|
||||
true // follow referenced pointers
|
||||
true, // follow referenced pointers
|
||||
simplifier // disabled simplifier
|
||||
);
|
||||
|
||||
CodeUnitFormat cuFormat = new CodeUnitFormat(formatOptions);
|
||||
@ -628,9 +631,9 @@ class ProgramTextWriter {
|
||||
if (options.isHTML()) {
|
||||
Reference ref =
|
||||
cu.getProgram()
|
||||
.getReferenceManager()
|
||||
.getPrimaryReferenceFrom(cuAddress,
|
||||
i);
|
||||
.getReferenceManager()
|
||||
.getPrimaryReferenceFrom(cuAddress,
|
||||
i);
|
||||
addReferenceLinkedText(ref, opReps[i], true);
|
||||
}
|
||||
else {
|
||||
|
@ -0,0 +1,300 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.app.util.template;
|
||||
|
||||
import ghidra.GhidraOptions;
|
||||
import ghidra.framework.options.Options;
|
||||
import ghidra.framework.options.ToolOptions;
|
||||
import ghidra.util.HelpLocation;
|
||||
|
||||
/**
|
||||
* Class for simplify names with template data. This class can be used with tool options or
|
||||
* as a stand alone configurable simplifier.
|
||||
*/
|
||||
public class TemplateSimplifier {
|
||||
public static final String SUB_OPTION_NAME = "Templates";
|
||||
|
||||
public static final String SIMPLIFY_TEMPLATES_OPTION =
|
||||
SUB_OPTION_NAME + ".Simplify Templated Names";
|
||||
public static final String TEMPLATE_NESTING_DEPTH_OPTION =
|
||||
SUB_OPTION_NAME + ".Max Template Depth";
|
||||
public static final String MAX_TEMPLATE_LENGTH_OPTION =
|
||||
SUB_OPTION_NAME + ".Max Template Length";
|
||||
public static final String MIN_TEMPLATE_LENGTH_OPTION =
|
||||
SUB_OPTION_NAME + ".Min Template Length";
|
||||
|
||||
public static final String SIMPLY_TEMPLATES_DESCRIPTION =
|
||||
"Determines whether to diplay templated names in a simplified form.";
|
||||
public static final String TEMPLATE_NESTING_DEPTH_DESCRIPTION =
|
||||
"Maximum template depth to display when simplify templated names.";
|
||||
public static final String MAX_TEMPLATE_LENGTH_DESCRIPTION =
|
||||
"Maximum number of characters to display in a template before truncating the name in the middle.";
|
||||
public static final String MIN_TEMPLATE_LENGTH_DESCRIPTION =
|
||||
"Minumum size of template to be simplified";
|
||||
|
||||
private boolean doSimplify = true;
|
||||
private int templateNestingDepth = 0;
|
||||
private int maxTemplateLength = 20;
|
||||
private int minTemplateLength = 10;
|
||||
|
||||
/**
|
||||
* Constructor to use for a TemplateSimplifier that doesn't use values from ToolOptions
|
||||
*/
|
||||
public TemplateSimplifier() {
|
||||
// constructs using standard simplifying options.
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor to use for a TemplateSimplifier that operates using the current values in
|
||||
* the tool options
|
||||
* @param fieldOptions the "Listing Field" options
|
||||
*/
|
||||
public TemplateSimplifier(ToolOptions fieldOptions) {
|
||||
checkForCorrectOptions(fieldOptions);
|
||||
ensureRegistered(fieldOptions);
|
||||
loadOptions(fieldOptions);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the template nesting depth to be simplified. A depth of 0 simplifies the entire
|
||||
* template portion of the name (everything in between <>). A depth of 1 leaves one level of
|
||||
* template information
|
||||
* @param depth the nesting depth
|
||||
*/
|
||||
public void setNestingDepth(int depth) {
|
||||
this.templateNestingDepth = depth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the nesting depth for simplification
|
||||
* @return the nesting depth for simplification
|
||||
*/
|
||||
public int getNestingDepth() {
|
||||
return templateNestingDepth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the maximum length do display the template portion. If, after any nesting,
|
||||
* simplification, the resulting template string is longer that the max length, the middle
|
||||
* portion will be replaced with "..." to reduce the template string to the given max length.
|
||||
* @param maxLength the max length of a template to display
|
||||
*/
|
||||
public void setMaxTemplateLength(int maxLength) {
|
||||
this.maxTemplateLength = maxLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the maximum length that a template will display.
|
||||
* @return the maximum length that a template will display
|
||||
*/
|
||||
public int getMaxTemplateLength() {
|
||||
return maxTemplateLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets if this TemplateSimplifier is enabled. If disabled, the {@link #simplify(String)}
|
||||
* method will return the input string.
|
||||
* @param doSimplify true to do simplification, false to do nothing
|
||||
*/
|
||||
public void setEnabled(boolean doSimplify) {
|
||||
this.doSimplify = doSimplify;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if this TemplateSimplifier is enabled.
|
||||
* @return if this TemplateSimplifier is enabled
|
||||
*/
|
||||
public boolean isEnabled() {
|
||||
return doSimplify;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the minimum length for a template string to be simplified. In other words, template
|
||||
* strings less than this length will not be changed.
|
||||
* @param minLength the minimum length to simplify
|
||||
*/
|
||||
public void setMinimumTemplateLength(int minLength) {
|
||||
this.minTemplateLength = minLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the minimum length of a template string that will be simplified.
|
||||
* @return the minimum length of a template string that will be simplified.
|
||||
*/
|
||||
public int getMinimumTemplateLength() {
|
||||
return minTemplateLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Simplifies any template string in the given input base on the current simplification
|
||||
* settings.
|
||||
* @param input the input string to be simplified
|
||||
* @return a simplified string
|
||||
*/
|
||||
public String simplify(String input) {
|
||||
if (!doSimplify) {
|
||||
return input;
|
||||
}
|
||||
return doSimplify(input, templateNestingDepth);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reloads the current simplification settings from the given field options
|
||||
* @param fieldOptions the options to retrieve the simplification settings.
|
||||
*/
|
||||
public void reloadFromOptions(ToolOptions fieldOptions) {
|
||||
checkForCorrectOptions(fieldOptions);
|
||||
loadOptions(fieldOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notification that options have changed
|
||||
* @param options the options object that has changed values
|
||||
* @param optionName the name of the options that changed
|
||||
* @param oldValue the old value for the option that changed
|
||||
* @param newValue the new value for the option that changed
|
||||
* @return true if the option that changed was a template simplification option
|
||||
*/
|
||||
public boolean fieldOptionsChanged(Options options, String optionName, Object oldValue,
|
||||
Object newValue) {
|
||||
if (optionName.equals(SIMPLIFY_TEMPLATES_OPTION)) {
|
||||
doSimplify = (Boolean) newValue;
|
||||
return true;
|
||||
}
|
||||
if (optionName.equals(TEMPLATE_NESTING_DEPTH_OPTION)) {
|
||||
templateNestingDepth = (Integer) newValue;
|
||||
return true;
|
||||
}
|
||||
if (optionName.equals(MAX_TEMPLATE_LENGTH_OPTION)) {
|
||||
maxTemplateLength = (Integer) newValue;
|
||||
return true;
|
||||
}
|
||||
if (optionName.equals(MIN_TEMPLATE_LENGTH_OPTION)) {
|
||||
minTemplateLength = (Integer) newValue;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private String doSimplify(String input, int depth) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
int pos = 0;
|
||||
TemplateString ts;
|
||||
while ((ts = findTemplateString(input, pos)) != null) {
|
||||
builder.append(input.substring(pos, ts.start));
|
||||
String template = ts.getTemplate();
|
||||
if (depth == 0) {
|
||||
builder.append("<");
|
||||
if (template.length() <= minTemplateLength) {
|
||||
builder.append(template);
|
||||
}
|
||||
builder.append(">");
|
||||
}
|
||||
else {
|
||||
builder.append("<");
|
||||
String simplifiedTemplate = doSimplify(template, depth - 1);
|
||||
if (simplifiedTemplate.length() > maxTemplateLength) {
|
||||
simplifiedTemplate = middleTruncate(template);
|
||||
}
|
||||
builder.append(simplifiedTemplate);
|
||||
builder.append(">");
|
||||
}
|
||||
pos = ts.end + 1;
|
||||
}
|
||||
builder.append(input.substring(pos));
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
private String middleTruncate(String input) {
|
||||
int partSize = maxTemplateLength / 2;
|
||||
return input.substring(0, partSize) + "..." + input.substring(input.length() - partSize);
|
||||
}
|
||||
|
||||
private static TemplateString findTemplateString(String input, int pos) {
|
||||
for (int i = pos; i < input.length(); i++) {
|
||||
char c = input.charAt(i);
|
||||
if (c == '<') {
|
||||
int end = findMatchingEnd(input, i + 1);
|
||||
if (end > i) {
|
||||
return new TemplateString(input, i, end);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static int findMatchingEnd(String input, int start) {
|
||||
int depth = 0;
|
||||
for (int i = start; i < input.length(); i++) {
|
||||
char c = input.charAt(i);
|
||||
if (c == '>') {
|
||||
if (depth == 0) {
|
||||
return i;
|
||||
}
|
||||
depth--;
|
||||
}
|
||||
else if (c == '<') {
|
||||
depth++;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private record TemplateString(String input, int start, int end) {
|
||||
String getTemplate() {
|
||||
return input.substring(start + 1, end); // don't include the enclosing <> chars
|
||||
}
|
||||
}
|
||||
|
||||
private void loadOptions(ToolOptions options) {
|
||||
doSimplify = options.getBoolean(SIMPLIFY_TEMPLATES_OPTION, doSimplify);
|
||||
templateNestingDepth = options.getInt(TEMPLATE_NESTING_DEPTH_OPTION, templateNestingDepth);
|
||||
maxTemplateLength = options.getInt(MAX_TEMPLATE_LENGTH_OPTION, maxTemplateLength);
|
||||
minTemplateLength = options.getInt(MIN_TEMPLATE_LENGTH_OPTION, minTemplateLength);
|
||||
}
|
||||
|
||||
private void checkForCorrectOptions(ToolOptions fieldOptions) {
|
||||
if (!GhidraOptions.CATEGORY_BROWSER_FIELDS.equals(fieldOptions.getName())) {
|
||||
throw new IllegalArgumentException(
|
||||
"Expected options named \"" + GhidraOptions.CATEGORY_BROWSER_FIELDS + "\", not \"" +
|
||||
fieldOptions.getName() + "\"");
|
||||
}
|
||||
}
|
||||
|
||||
private void ensureRegistered(Options options) {
|
||||
if (options.isRegistered(SIMPLIFY_TEMPLATES_OPTION)) {
|
||||
return;
|
||||
}
|
||||
|
||||
HelpLocation help = new HelpLocation("CodeBrowserPlugin", "Template Display Options");
|
||||
|
||||
options.getOptions(SUB_OPTION_NAME).setOptionsHelpLocation(help);
|
||||
|
||||
options.registerOption(SIMPLIFY_TEMPLATES_OPTION, doSimplify, help,
|
||||
SIMPLY_TEMPLATES_DESCRIPTION);
|
||||
|
||||
options.registerOption(TEMPLATE_NESTING_DEPTH_OPTION, templateNestingDepth, help,
|
||||
TEMPLATE_NESTING_DEPTH_DESCRIPTION);
|
||||
|
||||
options.registerOption(MAX_TEMPLATE_LENGTH_OPTION, maxTemplateLength, help,
|
||||
MAX_TEMPLATE_LENGTH_DESCRIPTION);
|
||||
|
||||
options.registerOption(MIN_TEMPLATE_LENGTH_OPTION, minTemplateLength, help,
|
||||
MIN_TEMPLATE_LENGTH_DESCRIPTION);
|
||||
}
|
||||
}
|
@ -20,6 +20,7 @@ import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
|
||||
import ghidra.GhidraOptions;
|
||||
import ghidra.app.util.template.TemplateSimplifier;
|
||||
import ghidra.framework.options.*;
|
||||
import ghidra.program.model.listing.CodeUnitFormatOptions;
|
||||
import ghidra.util.HelpLocation;
|
||||
@ -103,7 +104,7 @@ public class BrowserCodeUnitFormatOptions extends CodeUnitFormatOptions
|
||||
BrowserCodeUnitFormatOptions(ToolOptions fieldOptions, boolean autoUpdate) {
|
||||
this.fieldOptions = fieldOptions;
|
||||
this.displayOptions = new OptionsBasedDataTypeDisplayOptions(fieldOptions);
|
||||
|
||||
templateSimplifier = new TemplateSimplifier(fieldOptions);
|
||||
boolean exists = fieldOptions.isRegistered(NAMESPACE_OPTIONS);
|
||||
|
||||
if (!exists) {
|
||||
@ -144,7 +145,10 @@ public class BrowserCodeUnitFormatOptions extends CodeUnitFormatOptions
|
||||
@Override
|
||||
public void optionsChanged(ToolOptions options, String optionName, Object oldValue,
|
||||
Object newValue) {
|
||||
if (optionName.equals(GhidraOptions.SHOW_BLOCK_NAME_OPTION) ||
|
||||
if (templateSimplifier.fieldOptionsChanged(options, optionName, oldValue, newValue)) {
|
||||
notifyListeners();
|
||||
}
|
||||
else if (optionName.equals(GhidraOptions.SHOW_BLOCK_NAME_OPTION) ||
|
||||
optionName.equals(REGISTER_VARIABLE_MARKUP_OPTION) ||
|
||||
optionName.equals(STACK_VARIABLE_MARKUP_OPTION) ||
|
||||
optionName.equals(INFERRED_VARIABLE_MARKUP_OPTION) ||
|
||||
|
@ -21,6 +21,7 @@ import java.math.BigInteger;
|
||||
import docking.widgets.fieldpanel.support.FieldLocation;
|
||||
import generic.theme.Gui;
|
||||
import ghidra.app.util.HighlightProvider;
|
||||
import ghidra.app.util.template.TemplateSimplifier;
|
||||
import ghidra.app.util.viewer.format.FieldFormatModel;
|
||||
import ghidra.app.util.viewer.proxy.ProxyObj;
|
||||
import ghidra.framework.options.Options;
|
||||
@ -54,6 +55,7 @@ public abstract class FieldFactory implements ExtensionPoint {
|
||||
|
||||
protected String colorOptionName;
|
||||
protected String styleOptionName;
|
||||
private TemplateSimplifier templateSimplifier;
|
||||
|
||||
/**
|
||||
* Base constructor
|
||||
@ -72,14 +74,14 @@ public abstract class FieldFactory implements ExtensionPoint {
|
||||
styleOptionName = name + " Style";
|
||||
|
||||
width = 100;
|
||||
|
||||
templateSimplifier = model.getFormatManager().getTemplateSimplifier();
|
||||
initDisplayOptions(displayOptions);
|
||||
initFieldOptions(fieldOptions);
|
||||
}
|
||||
|
||||
protected void initFieldOptions(Options fieldOptions) {
|
||||
fieldOptions.getOptions(name)
|
||||
.setOptionsHelpLocation(new HelpLocation("CodeBrowserPlugin", name));
|
||||
.setOptionsHelpLocation(new HelpLocation("CodeBrowserPlugin", name));
|
||||
}
|
||||
|
||||
protected void initDisplayOptions(Options displayOptions) {
|
||||
@ -314,4 +316,8 @@ public abstract class FieldFactory implements ExtensionPoint {
|
||||
fontMetrics[i] = Toolkit.getDefaultToolkit().getFontMetrics(font);
|
||||
}
|
||||
}
|
||||
|
||||
protected String simplifyTemplates(String input) {
|
||||
return templateSimplifier.simplify(input);
|
||||
}
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ public class FunctionSignatureFieldFactory extends FieldFactory {
|
||||
* @param fieldOptions the Options for field specific properties.
|
||||
*/
|
||||
public FunctionSignatureFieldFactory(FieldFormatModel model, HighlightProvider hlProvider,
|
||||
Options displayOptions, Options fieldOptions) {
|
||||
ToolOptions displayOptions, ToolOptions fieldOptions) {
|
||||
super(FIELD_NAME, model, hlProvider, displayOptions, fieldOptions);
|
||||
|
||||
fieldOptions.registerOption(DISPLAY_NAMESPACE, false, null,
|
||||
@ -100,7 +100,7 @@ public class FunctionSignatureFieldFactory extends FieldFactory {
|
||||
elementIndex++;
|
||||
}
|
||||
|
||||
// noreturn
|
||||
// no return
|
||||
if (function.hasNoReturn()) {
|
||||
as = new AttributedString(Function.NORETURN + " ", FunctionColors.RETURN_TYPE,
|
||||
getMetrics());
|
||||
@ -110,7 +110,9 @@ public class FunctionSignatureFieldFactory extends FieldFactory {
|
||||
}
|
||||
|
||||
// return type
|
||||
as = new AttributedString(function.getReturn().getFormalDataType().getDisplayName() + " ",
|
||||
String returnTypeName = function.getReturn().getFormalDataType().getDisplayName();
|
||||
returnTypeName = simplifyTemplates(returnTypeName);
|
||||
as = new AttributedString(returnTypeName + " ",
|
||||
FunctionColors.RETURN_TYPE, getMetrics());
|
||||
textElements.add(new FunctionReturnTypeFieldElement(as, elementIndex, 0, startCol));
|
||||
startCol += as.length();
|
||||
@ -126,14 +128,14 @@ public class FunctionSignatureFieldFactory extends FieldFactory {
|
||||
as = new AttributedString(callingConvention + " ", FunctionColors.RETURN_TYPE,
|
||||
getMetrics());
|
||||
textElements
|
||||
.add(new FunctionCallingConventionFieldElement(as, elementIndex, 0, startCol));
|
||||
.add(new FunctionCallingConventionFieldElement(as, elementIndex, 0, startCol));
|
||||
startCol += as.length();
|
||||
elementIndex++;
|
||||
}
|
||||
|
||||
// function name
|
||||
as = new AttributedString(function.getName(displayFunctionScope),
|
||||
getFunctionNameColor(function), getMetrics());
|
||||
String functionName = simplifyTemplates(function.getName(displayFunctionScope));
|
||||
as = new AttributedString(functionName, getFunctionNameColor(function), getMetrics());
|
||||
textElements.add(new FunctionNameFieldElement(as, elementIndex, 0, startCol));
|
||||
startCol += as.length();
|
||||
elementIndex++;
|
||||
@ -159,15 +161,15 @@ public class FunctionSignatureFieldFactory extends FieldFactory {
|
||||
Color pcolor =
|
||||
params[i].isAutoParameter() ? FunctionColors.PARAM_AUTO : FunctionColors.PARAM;
|
||||
|
||||
String text = params[i].getFormalDataType().getDisplayName() + " ";
|
||||
as = new AttributedString(text, pcolor, getMetrics());
|
||||
String dtName = simplifyTemplates(params[i].getFormalDataType().getDisplayName() + " ");
|
||||
as = new AttributedString(dtName, pcolor, getMetrics());
|
||||
textElements.add(
|
||||
new FunctionParameterFieldElement(as, elementIndex, paramOffset, startCol, i));
|
||||
startCol += as.length();
|
||||
paramOffset += as.length();
|
||||
elementIndex++;
|
||||
|
||||
text = params[i].getName();
|
||||
String text = params[i].getName();
|
||||
as = new AttributedString(text, pcolor, getMetrics());
|
||||
textElements.add(
|
||||
new FunctionParameterNameFieldElement(as, elementIndex, paramOffset, startCol, i));
|
||||
@ -381,7 +383,6 @@ public class FunctionSignatureFieldFactory extends FieldFactory {
|
||||
@Override
|
||||
public void fieldOptionsChanged(Options options, String optionName, Object oldValue,
|
||||
Object newValue) {
|
||||
|
||||
if (optionName.equals(DISPLAY_NAMESPACE)) {
|
||||
displayFunctionScope = ((Boolean) newValue).booleanValue();
|
||||
model.update();
|
||||
|
@ -250,27 +250,26 @@ public class LabelFieldFactory extends FieldFactory {
|
||||
private String checkLabelString(Symbol symbol, Program program) {
|
||||
|
||||
if (!displayLocalNamespace && !displayNonLocalNamespace) {
|
||||
return symbol.getName(); // no namespaces being shown
|
||||
return simplifyTemplates(symbol.getName()); // no namespaces being shown
|
||||
}
|
||||
|
||||
Namespace addressNamespace = program.getSymbolTable().getNamespace(symbol.getAddress());
|
||||
Namespace symbolNamespace = symbol.getParentNamespace();
|
||||
boolean isLocal = symbolNamespace.equals(addressNamespace);
|
||||
if (!isLocal) {
|
||||
return symbol.getName(displayNonLocalNamespace);
|
||||
return simplifyTemplates(symbol.getName(displayNonLocalNamespace));
|
||||
}
|
||||
|
||||
// O.K., we ARE a local namespace, how to display it?
|
||||
if (!displayLocalNamespace) {
|
||||
return symbol.getName();
|
||||
return simplifyTemplates(symbol.getName());
|
||||
}
|
||||
|
||||
// use the namespace name or a custom, user-defined value
|
||||
if (useLocalPrefixOverride) {
|
||||
return localPrefixText + symbol.getName(false);
|
||||
return simplifyTemplates(localPrefixText + symbol.getName(false));
|
||||
}
|
||||
return symbol.getName(true);
|
||||
|
||||
return simplifyTemplates(symbol.getName(true));
|
||||
}
|
||||
|
||||
private List<Address> getOffcutReferenceAddress(CodeUnit cu) {
|
||||
|
@ -491,6 +491,7 @@ abstract class OperandFieldHelper extends FieldFactory {
|
||||
}
|
||||
|
||||
ColorStyleAttributes attributes = getOpAttributes(opElem, inst, opIndex);
|
||||
|
||||
AttributedString as = new AttributedString(opElem.toString(), attributes.colorAttribute,
|
||||
getMetrics(attributes.styleAttribute), underline, ListingColors.UNDERLINE);
|
||||
elements.add(new OperandFieldElement(as, opIndex, subOpIndex, characterOffset));
|
||||
|
@ -25,7 +25,6 @@ import ghidra.app.util.HighlightProvider;
|
||||
import ghidra.app.util.viewer.format.FieldFormatModel;
|
||||
import ghidra.app.util.viewer.proxy.FunctionProxy;
|
||||
import ghidra.app.util.viewer.proxy.ProxyObj;
|
||||
import ghidra.framework.options.Options;
|
||||
import ghidra.framework.options.ToolOptions;
|
||||
import ghidra.program.model.listing.Function;
|
||||
import ghidra.program.model.listing.Library;
|
||||
@ -56,7 +55,7 @@ public class ThunkedFunctionFieldFactory extends FieldFactory {
|
||||
* @param fieldOptions the Options for field specific properties.
|
||||
*/
|
||||
public ThunkedFunctionFieldFactory(FieldFormatModel model, HighlightProvider hlProvider,
|
||||
ToolOptions displayOptions, Options fieldOptions) {
|
||||
ToolOptions displayOptions, ToolOptions fieldOptions) {
|
||||
super(FIELD_NAME, model, hlProvider, displayOptions, fieldOptions);
|
||||
}
|
||||
|
||||
@ -96,8 +95,9 @@ public class ThunkedFunctionFieldFactory extends FieldFactory {
|
||||
as = new AttributedString("Thunked-Function: ", ListingColors.SEPARATOR, getMetrics());
|
||||
textElements.add(new TextFieldElement(as, elementIndex++, 0));
|
||||
|
||||
as = new AttributedString(thunkedFunction.getName(true),
|
||||
getThunkedFunctionNameColor(thunkedFunction), getMetrics());
|
||||
String functionName = simplifyTemplates(thunkedFunction.getName(true));
|
||||
as = new AttributedString(functionName, getThunkedFunctionNameColor(thunkedFunction),
|
||||
getMetrics());
|
||||
textElements.add(new TextFieldElement(as, elementIndex++, 0));
|
||||
|
||||
return ListingTextField.createSingleLineTextField(this, proxy,
|
||||
|
@ -23,7 +23,6 @@ import ghidra.app.util.HighlightProvider;
|
||||
import ghidra.app.util.viewer.format.FieldFormatModel;
|
||||
import ghidra.app.util.viewer.proxy.ProxyObj;
|
||||
import ghidra.app.util.viewer.proxy.VariableProxy;
|
||||
import ghidra.framework.options.Options;
|
||||
import ghidra.framework.options.ToolOptions;
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.program.model.listing.Parameter;
|
||||
@ -52,7 +51,7 @@ public class VariableTypeFieldFactory extends AbstractVariableFieldFactory {
|
||||
* @param fieldOptions the Options for field specific properties.
|
||||
*/
|
||||
private VariableTypeFieldFactory(FieldFormatModel model, HighlightProvider hlProvider,
|
||||
Options displayOptions, Options fieldOptions) {
|
||||
ToolOptions displayOptions, ToolOptions fieldOptions) {
|
||||
super(FIELD_NAME, model, hlProvider, displayOptions, fieldOptions);
|
||||
}
|
||||
|
||||
@ -65,24 +64,31 @@ public class VariableTypeFieldFactory extends AbstractVariableFieldFactory {
|
||||
if (!enabled || !(obj instanceof Variable)) {
|
||||
return null;
|
||||
}
|
||||
Variable sv = (Variable) obj;
|
||||
Variable variable = (Variable) obj;
|
||||
|
||||
DataType dt;
|
||||
if (sv instanceof Parameter) {
|
||||
dt = ((Parameter) sv).getFormalDataType();
|
||||
if (variable instanceof Parameter) {
|
||||
dt = ((Parameter) variable).getFormalDataType();
|
||||
}
|
||||
else {
|
||||
dt = sv.getDataType();
|
||||
dt = variable.getDataType();
|
||||
}
|
||||
String dtName = (dt != null) ? dt.getDisplayName() : null;
|
||||
|
||||
String dtName = getDataTypeName(dt);
|
||||
AttributedString as =
|
||||
new AttributedString((dtName != null) ? dtName : "", getColor(sv), getMetrics(sv));
|
||||
new AttributedString(dtName, getColor(variable), getMetrics(variable));
|
||||
FieldElement field = new TextFieldElement(as, 0, 0);
|
||||
return ListingTextField.createSingleLineTextField(this, proxy, field, startX + varWidth,
|
||||
width, hlProvider);
|
||||
}
|
||||
|
||||
private String getDataTypeName(DataType dt) {
|
||||
if (dt == null) {
|
||||
return "";
|
||||
}
|
||||
String dtName = dt.getName();
|
||||
return dtName == null ? "" : simplifyTemplates(dtName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.app.util.viewer.field.FieldFactory#getProgramLocation(int, int, ghidra.app.util.viewer.field.ListingField)
|
||||
*/
|
||||
|
@ -23,6 +23,7 @@ import org.jdom.Element;
|
||||
|
||||
import docking.widgets.fieldpanel.support.Highlight;
|
||||
import ghidra.app.util.HighlightProvider;
|
||||
import ghidra.app.util.template.TemplateSimplifier;
|
||||
import ghidra.app.util.viewer.field.*;
|
||||
import ghidra.framework.options.*;
|
||||
import ghidra.framework.plugintool.ServiceProvider;
|
||||
@ -67,6 +68,7 @@ public class FormatManager implements OptionsChangeListener {
|
||||
private ServiceProvider serviceProvider;
|
||||
private int arrayValuesPerLine = 1;
|
||||
private boolean groupArrayElements = true;
|
||||
TemplateSimplifier templateSimplifier;
|
||||
|
||||
// NOTE: Unused custom format code was removed. The custom format code last existed in
|
||||
// commit #204e7892bf2f110ebb05ca4beee3fe5b397f88c9.
|
||||
@ -80,6 +82,7 @@ public class FormatManager implements OptionsChangeListener {
|
||||
public FormatManager(ToolOptions displayOptions, ToolOptions fieldOptions) {
|
||||
this.fieldOptions = fieldOptions;
|
||||
this.displayOptions = displayOptions;
|
||||
this.templateSimplifier = new TemplateSimplifier(fieldOptions);
|
||||
highlightProvider = new MultipleHighlighterProvider();
|
||||
getFactorys();
|
||||
for (int i = 0; i < NUM_MODELS; i++) {
|
||||
@ -153,7 +156,7 @@ public class FormatManager implements OptionsChangeListener {
|
||||
/**
|
||||
* Adds a listener to be notified when a format changes.
|
||||
*
|
||||
* @param listener the listener to be added.
|
||||
* @param listener the listener to be added
|
||||
*/
|
||||
public void addFormatModelListener(FormatModelListener listener) {
|
||||
formatListeners.add(listener);
|
||||
@ -171,6 +174,7 @@ public class FormatManager implements OptionsChangeListener {
|
||||
|
||||
/**
|
||||
* Returns the total number of model in the format manager.
|
||||
* @return the total number of model in the format manager
|
||||
*/
|
||||
public int getNumModels() {
|
||||
return NUM_MODELS;
|
||||
@ -180,27 +184,31 @@ public class FormatManager implements OptionsChangeListener {
|
||||
* Returns the format model for the given index.
|
||||
*
|
||||
* @param index the index of the format model to return.
|
||||
* @return the format model for the given index
|
||||
*/
|
||||
public FieldFormatModel getModel(int index) {
|
||||
return models[index];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the format model for the address break (divider)
|
||||
* Returns the format model for the address break (divider).
|
||||
* @return the format model for the address break (divider)
|
||||
*/
|
||||
public FieldFormatModel getDividerModel() {
|
||||
return models[FieldFormatModel.DIVIDER];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the format model for the plate field
|
||||
* Returns the format model for the plate field.
|
||||
* @return the format model for the plate field
|
||||
*/
|
||||
public FieldFormatModel getPlateFormat() {
|
||||
return models[FieldFormatModel.PLATE];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the format model for the function signature
|
||||
* Returns the format model for the function signature.
|
||||
* @return the format model for the function signature
|
||||
*/
|
||||
public FieldFormatModel getFunctionFormat() {
|
||||
return models[FieldFormatModel.FUNCTION];
|
||||
@ -208,6 +216,7 @@ public class FormatManager implements OptionsChangeListener {
|
||||
|
||||
/**
|
||||
* Returns the format model for the function variables.
|
||||
* @return the format model for the function variables
|
||||
*/
|
||||
public FieldFormatModel getFunctionVarFormat() {
|
||||
return models[FieldFormatModel.FUNCTION_VARS];
|
||||
@ -215,6 +224,7 @@ public class FormatManager implements OptionsChangeListener {
|
||||
|
||||
/**
|
||||
* Returns the format model for a code unit.
|
||||
* @return the format model for a code unit
|
||||
*/
|
||||
public FieldFormatModel getCodeUnitFormat() {
|
||||
return models[FieldFormatModel.INSTRUCTION_OR_DATA];
|
||||
@ -261,6 +271,7 @@ public class FormatManager implements OptionsChangeListener {
|
||||
|
||||
/**
|
||||
* Returns the Options used for display properties.
|
||||
* @return the Options used for display properties.
|
||||
*/
|
||||
public ToolOptions getDisplayOptions() {
|
||||
return displayOptions;
|
||||
@ -268,11 +279,20 @@ public class FormatManager implements OptionsChangeListener {
|
||||
|
||||
/**
|
||||
* Returns the Options used for field specific properties.
|
||||
* @return the Options used for field specific properties
|
||||
*/
|
||||
public ToolOptions getFieldOptions() {
|
||||
return fieldOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the template simplifier.
|
||||
* @return the template simplifier.
|
||||
*/
|
||||
public TemplateSimplifier getTemplateSimplifier() {
|
||||
return templateSimplifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies listeners that the given model has changed.
|
||||
*
|
||||
@ -852,6 +872,7 @@ public class FormatManager implements OptionsChangeListener {
|
||||
}
|
||||
}
|
||||
else if (options == fieldOptions) {
|
||||
templateSimplifier.fieldOptionsChanged(options, name, oldValue, newValue);
|
||||
for (int i = 0; i < NUM_MODELS; i++) {
|
||||
models[i].fieldOptionsChanged(options, name, oldValue, newValue);
|
||||
}
|
||||
|
@ -322,17 +322,19 @@ public class CodeUnitFormat {
|
||||
}
|
||||
else if (options.includeInferredVariableMarkup) {
|
||||
boolean isRead = isRead(reg, instr);
|
||||
Variable regVar = program.getFunctionManager().getReferencedVariable(
|
||||
instr.getMinAddress(), reg.getAddress(), reg.getMinimumByteSize(), isRead);
|
||||
Variable regVar = program.getFunctionManager()
|
||||
.getReferencedVariable(
|
||||
instr.getMinAddress(), reg.getAddress(), reg.getMinimumByteSize(), isRead);
|
||||
if (regVar != null) {
|
||||
// TODO: If register appears more than once, how can we distinguish read vs. write occurrence in operands
|
||||
if (isRead && isWritten(reg, instr) && !hasRegisterWriteReference(instr, reg) &&
|
||||
instr.getRegister(opIndex) != null) {
|
||||
// If register both read and written and there are no write references for this instruction
|
||||
// see if there is only one reference to choose from - if not we can't determine how to markup
|
||||
Variable regWriteVar = program.getFunctionManager().getReferencedVariable(
|
||||
instr.getMinAddress(), reg.getAddress(), reg.getMinimumByteSize(),
|
||||
false);
|
||||
Variable regWriteVar = program.getFunctionManager()
|
||||
.getReferencedVariable(
|
||||
instr.getMinAddress(), reg.getAddress(), reg.getMinimumByteSize(),
|
||||
false);
|
||||
if (regWriteVar != regVar) {
|
||||
continue; // TODO: tough case - not which operand is read vs. write!
|
||||
}
|
||||
@ -630,8 +632,10 @@ public class CodeUnitFormat {
|
||||
}
|
||||
|
||||
Variable regVar =
|
||||
instr.getProgram().getFunctionManager().getReferencedVariable(instr.getMinAddress(),
|
||||
associatedRegister.getAddress(), associatedRegister.getMinimumByteSize(), true);
|
||||
instr.getProgram()
|
||||
.getFunctionManager()
|
||||
.getReferencedVariable(instr.getMinAddress(),
|
||||
associatedRegister.getAddress(), associatedRegister.getMinimumByteSize(), true);
|
||||
if (regVar == null) {
|
||||
return false;
|
||||
}
|
||||
@ -1151,8 +1155,10 @@ public class CodeUnitFormat {
|
||||
public String getReferenceRepresentationString(CodeUnit fromCodeUnit, Reference ref) {
|
||||
// NOTE: The isRead param is false since it really only pertains to register references which should
|
||||
// generally only correspond to writes
|
||||
Variable refVar = fromCodeUnit.getProgram().getFunctionManager().getReferencedVariable(
|
||||
fromCodeUnit.getMinAddress(), ref.getToAddress(), 0, false);
|
||||
Variable refVar = fromCodeUnit.getProgram()
|
||||
.getFunctionManager()
|
||||
.getReferencedVariable(
|
||||
fromCodeUnit.getMinAddress(), ref.getToAddress(), 0, false);
|
||||
Object repObj = getReferenceRepresentation(fromCodeUnit, ref, refVar);
|
||||
return repObj != null ? repObj.toString() : null;
|
||||
}
|
||||
@ -1367,7 +1373,13 @@ public class CodeUnitFormat {
|
||||
}
|
||||
}
|
||||
String name = symbol.getName();
|
||||
return addNamespace(program, symbol.getParentNamespace(), name, markupAddress);
|
||||
String displayName =
|
||||
addNamespace(program, symbol.getParentNamespace(), name, markupAddress);
|
||||
return simplifyTemplate(displayName);
|
||||
}
|
||||
|
||||
private String simplifyTemplate(String name) {
|
||||
return options.simplifyTemplate(name);
|
||||
}
|
||||
|
||||
private boolean isStringData(CodeUnit cu) {
|
||||
@ -1379,7 +1391,7 @@ public class CodeUnitFormat {
|
||||
|
||||
private String getLabelStringForStringData(Data data, Symbol symbol) {
|
||||
if (!symbol.isDynamic()) {
|
||||
return symbol.getName();
|
||||
return options.simplifyTemplate(symbol.getName());
|
||||
}
|
||||
DataType dataType = data.getBaseDataType();
|
||||
|
||||
@ -1440,7 +1452,7 @@ public class CodeUnitFormat {
|
||||
|
||||
Symbol containingSymbol = program.getSymbolTable().getPrimarySymbol(instructionAddress);
|
||||
if (containingSymbol != null) {
|
||||
return containingSymbol.getName() + PLUS + diff;
|
||||
return options.simplifyTemplate(containingSymbol.getName()) + PLUS + diff;
|
||||
}
|
||||
return getDefaultOffcutString(offsym, instruction, diff, false);
|
||||
}
|
||||
@ -1464,10 +1476,11 @@ public class CodeUnitFormat {
|
||||
|
||||
protected String getDefaultOffcutString(Symbol symbol, CodeUnit cu, long diff,
|
||||
boolean decorate) {
|
||||
String name = options.simplifyTemplate(symbol.getName());
|
||||
if (decorate) {
|
||||
return symbol.getName() + ' ' + '(' + cu.getMinAddress() + PLUS + diff + ')';
|
||||
return name + ' ' + '(' + cu.getMinAddress() + PLUS + diff + ')';
|
||||
}
|
||||
return symbol.getName();
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -15,6 +15,7 @@
|
||||
*/
|
||||
package ghidra.program.model.listing;
|
||||
|
||||
import ghidra.app.util.template.TemplateSimplifier;
|
||||
import ghidra.program.model.data.DataTypeDisplayOptions;
|
||||
|
||||
public class CodeUnitFormatOptions {
|
||||
@ -80,9 +81,11 @@ public class CodeUnitFormatOptions {
|
||||
protected volatile boolean showOffcutInfo = true;
|
||||
|
||||
protected DataTypeDisplayOptions displayOptions = DataTypeDisplayOptions.DEFAULT;
|
||||
protected TemplateSimplifier templateSimplifier;
|
||||
|
||||
public CodeUnitFormatOptions() {
|
||||
// use default options;
|
||||
templateSimplifier = new TemplateSimplifier();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -93,6 +96,7 @@ public class CodeUnitFormatOptions {
|
||||
public CodeUnitFormatOptions(ShowBlockName showBlockName, ShowNamespace showNamespace) {
|
||||
this.showBlockName = showBlockName;
|
||||
this.showNamespace = showNamespace;
|
||||
templateSimplifier = new TemplateSimplifier();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -119,7 +123,7 @@ public class CodeUnitFormatOptions {
|
||||
String localPrefixOverride, boolean doRegVariableMarkup, boolean doStackVariableMarkup,
|
||||
boolean includeInferredVariableMarkup, boolean alwaysShowPrimaryReference,
|
||||
boolean includeScalarReferenceAdjustment, boolean showLibraryInNamespace,
|
||||
boolean followReferencedPointers) {
|
||||
boolean followReferencedPointers, TemplateSimplifier templateSimplifier) {
|
||||
this.showBlockName = showBlockName;
|
||||
this.showNamespace = showNamespace;
|
||||
this.showLibraryInNamespace = showLibraryInNamespace;
|
||||
@ -130,6 +134,7 @@ public class CodeUnitFormatOptions {
|
||||
this.alwaysShowPrimaryReference = alwaysShowPrimaryReference;
|
||||
this.followReferencedPointers = followReferencedPointers;
|
||||
this.includeScalarReferenceAdjustment = includeScalarReferenceAdjustment;
|
||||
this.templateSimplifier = templateSimplifier;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -139,4 +144,8 @@ public class CodeUnitFormatOptions {
|
||||
public ShowBlockName getShowBlockNameOption() {
|
||||
return showBlockName;
|
||||
}
|
||||
|
||||
public String simplifyTemplate(String name) {
|
||||
return templateSimplifier.simplify(name);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,115 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.app.util.template;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import generic.test.AbstractGenericTest;
|
||||
import ghidra.framework.options.ToolOptions;
|
||||
|
||||
public class TemplateSimplifierTest extends AbstractGenericTest {
|
||||
|
||||
private TemplateSimplifier simplifier = new TemplateSimplifier();
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
simplifier.setMinimumTemplateLength(0);
|
||||
simplifier.setNestingDepth(0);
|
||||
simplifier.setEnabled(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimplifyTemplates() {
|
||||
assertEquals("bob<>", simplify("bob<hey>"));
|
||||
assertEquals("bob<>", simplify("bob<foo<hey>>"));
|
||||
assertEquals("bob<foo<>", simplify("bob<foo<bar>"));
|
||||
assertEquals("bob<>", simplify("bob<foo<bar<hey>>>"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimplifyTemplatesDepth1() {
|
||||
simplifier.setNestingDepth(1);
|
||||
assertEquals("bob<hey>", simplify("bob<hey>"));
|
||||
assertEquals("bob<foo<>>", simplify("bob<foo<hey>>"));
|
||||
assertEquals("bob<foo<bar>", simplify("bob<foo<bar>"));
|
||||
assertEquals("bob<foo<>>", simplify("bob<foo<bar<hey>>>"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimplifyTemplatesDepth2() {
|
||||
simplifier.setNestingDepth(2);
|
||||
assertEquals("bob<hey>", simplify("bob<hey>"));
|
||||
assertEquals("bob<foo<hey>>", simplify("bob<foo<hey>>"));
|
||||
assertEquals("bob<foo<bar>", simplify("bob<foo<bar>"));
|
||||
assertEquals("bob<foo<bar<>>>", simplify("bob<foo<bar<hey>>>"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStripTemplatesWithMaxSize() {
|
||||
simplifier.setMaxTemplateLength(10);
|
||||
simplifier.setNestingDepth(5);
|
||||
assertEquals("bob<abcde...vwxyz>", simplify("bob<abcdefghijklmnopqrstuvwxyz>"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStripTemplatesWithMaxSizeAndNestedTemplates() {
|
||||
simplifier.setMaxTemplateLength(10);
|
||||
simplifier.setNestingDepth(5);
|
||||
assertEquals("bob<int, ...wxyz>>",
|
||||
simplify("bob<int, foo<abcdefghijklmnopqrstuvwxyz>>"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMinSizeToSimplify() {
|
||||
simplifier.setMinimumTemplateLength(5);
|
||||
assertEquals("bob<abcde>", simplify("bob<abcde>"));
|
||||
assertEquals("bob<>", simplify("bob<abcdef>"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOptionsGetRegistered() {
|
||||
ToolOptions options = new ToolOptions("Listing Fields");
|
||||
simplifier = new TemplateSimplifier(options);
|
||||
|
||||
assertTrue(options.isRegistered(TemplateSimplifier.SIMPLIFY_TEMPLATES_OPTION));
|
||||
assertTrue(options.isRegistered(TemplateSimplifier.MAX_TEMPLATE_LENGTH_OPTION));
|
||||
assertTrue(options.isRegistered(TemplateSimplifier.TEMPLATE_NESTING_DEPTH_OPTION));
|
||||
assertTrue(options.isRegistered(TemplateSimplifier.MIN_TEMPLATE_LENGTH_OPTION));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadsOptions() {
|
||||
ToolOptions options = new ToolOptions("Listing Fields");
|
||||
options.setBoolean(TemplateSimplifier.SIMPLIFY_TEMPLATES_OPTION, false);
|
||||
options.setInt(TemplateSimplifier.MAX_TEMPLATE_LENGTH_OPTION, 33);
|
||||
options.setInt(TemplateSimplifier.TEMPLATE_NESTING_DEPTH_OPTION, 3);
|
||||
options.setInt(TemplateSimplifier.MIN_TEMPLATE_LENGTH_OPTION, 7);
|
||||
simplifier = new TemplateSimplifier(options);
|
||||
|
||||
assertEquals(false, simplifier.isEnabled());
|
||||
assertEquals(33, simplifier.getMaxTemplateLength());
|
||||
assertEquals(3, simplifier.getNestingDepth());
|
||||
assertEquals(7, simplifier.getMinimumTemplateLength());
|
||||
}
|
||||
|
||||
private String simplify(String in) {
|
||||
return simplifier.simplify(in);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user