mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2024-11-22 04:05:39 +00:00
Help - Added a task to find unused help images; fixed showing in-memory
images in help
This commit is contained in:
parent
e8dcb3d0c4
commit
49436c44a9
@ -15,7 +15,6 @@
|
||||
*/
|
||||
package docking.help;
|
||||
|
||||
import java.awt.Image;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.io.*;
|
||||
@ -25,7 +24,6 @@ import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JEditorPane;
|
||||
import javax.swing.event.HyperlinkEvent;
|
||||
import javax.swing.event.HyperlinkListener;
|
||||
@ -380,20 +378,10 @@ public class GHelpHTMLEditorKit extends HTMLEditorKit {
|
||||
*/
|
||||
private class GHelpImageView extends ImageView {
|
||||
|
||||
private Image myImage;
|
||||
|
||||
public GHelpImageView(Element elem) {
|
||||
super(elem);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Image getImage() {
|
||||
if (myImage != null) {
|
||||
return myImage;
|
||||
}
|
||||
return super.getImage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public URL getImageURL() {
|
||||
|
||||
@ -419,10 +407,7 @@ public class GHelpHTMLEditorKit extends HTMLEditorKit {
|
||||
return null;
|
||||
}
|
||||
|
||||
ImageIcon icon = iconProvider.getIcon();
|
||||
myImage = icon.getImage();
|
||||
|
||||
URL url = iconProvider.getUrl();
|
||||
URL url = iconProvider.getOrCreateUrl();
|
||||
return url;
|
||||
}
|
||||
|
||||
|
@ -15,17 +15,30 @@
|
||||
*/
|
||||
package resources;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
|
||||
import javax.swing.ImageIcon;
|
||||
|
||||
import generic.Images;
|
||||
import generic.util.image.ImageUtils;
|
||||
import ghidra.util.Msg;
|
||||
|
||||
/**
|
||||
* A class that knows how to provide an icon and the URL for that icon
|
||||
* A class that knows how to provide an icon and the URL for that icon. If {@link #getUrl()}
|
||||
* returns a non-null value, then that is the URL used to originally load the icon in this class.
|
||||
*
|
||||
* <p>If {@link #getUrl()} returns null, then {@link #getOrCreateUrl()} can be used to create a
|
||||
* value URL by writing out the image for this class's icon.
|
||||
*/
|
||||
public class IconProvider {
|
||||
|
||||
private ImageIcon icon;
|
||||
private URL url;
|
||||
private URL tempUrl;
|
||||
private boolean tempFileFailed;
|
||||
|
||||
public IconProvider(ImageIcon icon, URL url) {
|
||||
this.icon = icon;
|
||||
@ -36,11 +49,76 @@ public class IconProvider {
|
||||
return icon;
|
||||
}
|
||||
|
||||
public boolean isInvalid() {
|
||||
return icon == null; // as long as we have an icon, we are valid, url or not
|
||||
}
|
||||
|
||||
public URL getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public boolean isInvalid() {
|
||||
return icon == null || url == null;
|
||||
/**
|
||||
* Returns the value of {@link #getUrl()} if it is non-null. Otherwise, this class will
|
||||
* attempt to create a temporary file containing the image of this class in order to return
|
||||
* a URL for that temp file. If a temporary file could not be created, then the URL
|
||||
* returned from this class will point to the
|
||||
* {@link ResourceManager#getDefaultIcon() default icon}.
|
||||
*
|
||||
* @return the URL
|
||||
*/
|
||||
public URL getOrCreateUrl() {
|
||||
if (url != null) {
|
||||
return url;
|
||||
}
|
||||
|
||||
createTempUrlAsNeeded();
|
||||
return tempUrl;
|
||||
}
|
||||
|
||||
private void createTempUrlAsNeeded() {
|
||||
if (testUrl(tempUrl)) {
|
||||
return;
|
||||
}
|
||||
|
||||
tempUrl = createTempUrl();
|
||||
if (tempUrl == null) {
|
||||
tempUrl = getDefaultUrl();
|
||||
}
|
||||
}
|
||||
|
||||
private URL createTempUrl() {
|
||||
if (tempFileFailed) {
|
||||
return null; // don't repeatedly attempt to create a temp file
|
||||
}
|
||||
|
||||
try {
|
||||
File imageFile = File.createTempFile("temp.help.icon", null);
|
||||
imageFile.deleteOnExit(); // don't let this linger
|
||||
ImageUtils.writeFile(icon.getImage(), imageFile);
|
||||
return imageFile.toURI().toURL();
|
||||
}
|
||||
catch (IOException e) {
|
||||
tempFileFailed = true;
|
||||
Msg.error(this, "Unable to write temp image to display in help for " +
|
||||
ResourceManager.getIconName(icon));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean testUrl(URL testUrl) {
|
||||
if (testUrl == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
return new File(testUrl.toURI()).exists();
|
||||
}
|
||||
catch (URISyntaxException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private URL getDefaultUrl() {
|
||||
return ResourceManager.getResource(Images.BOMB);
|
||||
}
|
||||
}
|
||||
|
@ -91,7 +91,7 @@ public class Icons {
|
||||
ResourceManager.loadImage("images/dialog-cancel.png", 10, 10), 6, 6)));
|
||||
public static final ImageIcon APPLY_BLOCKED_MATCH_ICON = ResourceManager.getImageIcon(
|
||||
new MultiIcon(ResourceManager.loadImage("images/kgpg.png"), new TranslateIcon(
|
||||
ResourceManager.loadImage("images/checkmark_green.png", 12, 12), 4, 0)));
|
||||
ResourceManager.loadImage("images/checkmark_green.gif", 12, 12), 4, 0)));
|
||||
|
||||
/**
|
||||
* Returns true if the given string is a Java code snippet that references this class
|
||||
@ -126,24 +126,6 @@ public class Icons {
|
||||
return new IconProvider(icon, url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a URL for the given code snippet if it is a field reference on this class
|
||||
*
|
||||
* @param snippet the snippet of Java code that references a field of this class
|
||||
* @return the URL; null if the snippet does not refer to a field of this class
|
||||
*/
|
||||
public static URL getUrlForIconsReference(String snippet) {
|
||||
|
||||
String fieldName = getIconName(snippet);
|
||||
if (fieldName == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ImageIcon icon = getIconByFieldName(fieldName);
|
||||
URL url = getUrlFromIcon(icon);
|
||||
return url;
|
||||
}
|
||||
|
||||
private static String getIconName(String snippet) {
|
||||
if (!isIconsReference(snippet)) {
|
||||
return null;
|
||||
@ -185,7 +167,7 @@ public class Icons {
|
||||
return url;
|
||||
}
|
||||
catch (MalformedURLException e) {
|
||||
Msg.debug(Icons.class, "Unable to get URL for icon: " + description, e);
|
||||
Msg.trace(Icons.class, "Unable to get URL for icon: " + description);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -160,19 +160,18 @@ public class MultiIcon implements Icon {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
// return getClass().getSimpleName() + "[" + getIconNames() + "]";
|
||||
return getDescription();
|
||||
return getClass().getSimpleName() + "[" + getIconNames() + "]";
|
||||
}
|
||||
|
||||
// private String getIconNames() {
|
||||
// StringBuffer buffy = new StringBuffer();
|
||||
// for (Icon icon : iconList) {
|
||||
// if (buffy.length() > 0) {
|
||||
// buffy.append(", ");
|
||||
// }
|
||||
// buffy.append(ResourceManager.getIconName(icon));
|
||||
// }
|
||||
//
|
||||
// return buffy.toString();
|
||||
// }
|
||||
private String getIconNames() {
|
||||
StringBuffer buffy = new StringBuffer();
|
||||
for (Icon icon : iconList) {
|
||||
if (buffy.length() > 0) {
|
||||
buffy.append(", ");
|
||||
}
|
||||
buffy.append(ResourceManager.getIconName(icon));
|
||||
}
|
||||
|
||||
return buffy.toString();
|
||||
}
|
||||
}
|
||||
|
@ -400,14 +400,18 @@ public class ResourceManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of this icon. If icon is an ImageIcon, its getDescription() is called to
|
||||
* get the name
|
||||
* Get the name of this icon. The value is usually going to be the URL from which the icon
|
||||
* was loaded
|
||||
*
|
||||
* @param icon the icon for which the name is desired
|
||||
* @return the name
|
||||
*/
|
||||
public static String getIconName(Icon icon) {
|
||||
String iconName = icon.toString();
|
||||
|
||||
if (icon instanceof FileBasedIcon) {
|
||||
return ((FileBasedIcon) icon).getFilename();
|
||||
}
|
||||
if (icon instanceof ImageIcon) {
|
||||
iconName = ((ImageIcon) icon).getDescription();
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import help.validator.location.*;
|
||||
import resources.IconProvider;
|
||||
import resources.Icons;
|
||||
|
||||
public class HelpBuildUtils {
|
||||
@ -536,6 +537,7 @@ public class HelpBuildUtils {
|
||||
* locate files based upon relative references, specialized help system references (i.e.,
|
||||
* help/topics/...), and absolute URLs.
|
||||
*
|
||||
* @param sourceFile the source file path of the image reference
|
||||
* @param ref the reference text
|
||||
* @return an absolute path; null if the URI is remote
|
||||
* @throws URISyntaxException
|
||||
@ -544,15 +546,21 @@ public class HelpBuildUtils {
|
||||
throws URISyntaxException {
|
||||
|
||||
if (Icons.isIconsReference(ref)) {
|
||||
|
||||
// help system syntax: <img src="Icons.ERROR_ICON" />
|
||||
URL url = Icons.getUrlForIconsReference(ref);
|
||||
if (url == null) {
|
||||
IconProvider iconProvider = Icons.getIconForIconsReference(ref);
|
||||
if (iconProvider == null || iconProvider.isInvalid()) {
|
||||
// bad icon name
|
||||
return ImageLocation.createInvalidRuntimeLocation(sourceFile, ref);
|
||||
}
|
||||
|
||||
URI resolved = url.toURI();
|
||||
Path path = toPath(resolved);
|
||||
URL url = iconProvider.getUrl();
|
||||
URI resolved = null;
|
||||
Path path = null;
|
||||
if (url != null) { // we may have an icon with an invalid URL (e.g., a MultiIcon)
|
||||
resolved = url.toURI();
|
||||
path = toPath(resolved);
|
||||
}
|
||||
return ImageLocation.createRuntimeLocation(sourceFile, ref, resolved, path);
|
||||
}
|
||||
|
||||
|
@ -21,6 +21,9 @@ import java.nio.file.Path;
|
||||
/**
|
||||
* A class that represents the original location of an IMG tag along with its location
|
||||
* resolution within the help system.
|
||||
*
|
||||
* <p>Some images are represented by 'in memory' or 'runtime' values that do not have a valid
|
||||
* url.
|
||||
*/
|
||||
public class ImageLocation {
|
||||
|
||||
@ -30,8 +33,13 @@ public class ImageLocation {
|
||||
private Path resolvedPath;
|
||||
private URI resolvedUri;
|
||||
private boolean isRemote;
|
||||
|
||||
/** An image that is taken from an image loaded by a Java class (e.g., Icons.XYZ_ICON) */
|
||||
private boolean isRuntime;
|
||||
|
||||
/** A 'runtime' image that could not be located */
|
||||
private boolean invalidRuntimeImage;
|
||||
|
||||
public static ImageLocation createLocalLocation(Path sourceFile, String imageSrc,
|
||||
URI resolvedUri, Path resolvedPath) {
|
||||
|
||||
@ -61,6 +69,7 @@ public class ImageLocation {
|
||||
l.resolvedPath = null;
|
||||
l.isRemote = false;
|
||||
l.isRuntime = true;
|
||||
l.invalidRuntimeImage = true;
|
||||
return l;
|
||||
}
|
||||
|
||||
@ -84,48 +93,28 @@ public class ImageLocation {
|
||||
return sourceFile;
|
||||
}
|
||||
|
||||
public void setSourceFile(Path sourceFile) {
|
||||
this.sourceFile = sourceFile;
|
||||
}
|
||||
|
||||
public String getImageSrc() {
|
||||
return imageSrc;
|
||||
}
|
||||
|
||||
public void setImageSrc(String imageSrc) {
|
||||
this.imageSrc = imageSrc;
|
||||
}
|
||||
|
||||
public Path getResolvedPath() {
|
||||
return resolvedPath;
|
||||
}
|
||||
|
||||
public void setResolvedPath(Path resolvedPath) {
|
||||
this.resolvedPath = resolvedPath;
|
||||
}
|
||||
|
||||
public URI getResolvedUri() {
|
||||
return resolvedUri;
|
||||
}
|
||||
|
||||
public void setResolvedUri(URI resolvedUri) {
|
||||
this.resolvedUri = resolvedUri;
|
||||
}
|
||||
|
||||
public boolean isRemote() {
|
||||
return isRemote;
|
||||
}
|
||||
|
||||
public void setRemote(boolean isRemote) {
|
||||
this.isRemote = isRemote;
|
||||
}
|
||||
|
||||
public boolean isRuntime() {
|
||||
return isRuntime;
|
||||
}
|
||||
|
||||
public void setRuntime(boolean isRuntime) {
|
||||
this.isRuntime = isRuntime;
|
||||
public boolean isInvalidRuntimeImage() {
|
||||
return invalidRuntimeImage;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -120,14 +120,22 @@ public class JavaHelpValidator {
|
||||
return; // don't even try to verify a remote URL
|
||||
}
|
||||
|
||||
Path imagePath = img.getImageFile();
|
||||
if (imagePath == null) {
|
||||
unresolvedLinks.add(new NonExistentIMGFileInvalidLink(img));
|
||||
if (img.isRuntime()) {
|
||||
|
||||
//
|
||||
// The tool will load this image at runtime--don't perform normal validation
|
||||
// (runtime means an icon to be loaded from a Java file)
|
||||
//
|
||||
if (img.isInvalid()) {
|
||||
unresolvedLinks.add(new InvalidRuntimeIMGFileInvalidLink(img));
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (img.isRuntime()) {
|
||||
// the tool will load this image at runtime--don't perform normal validate
|
||||
Path imagePath = img.getImageFile();
|
||||
if (imagePath == null) {
|
||||
unresolvedLinks.add(new NonExistentIMGFileInvalidLink(img));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
* REVIEWED: YES
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -16,22 +15,25 @@
|
||||
*/
|
||||
package help.validator;
|
||||
|
||||
import help.GHelpBuilder;
|
||||
import help.HelpBuildUtils;
|
||||
import help.validator.location.HelpModuleLocation;
|
||||
import help.validator.model.IMG;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.*;
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.util.*;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import help.HelpBuildUtils;
|
||||
import help.validator.location.HelpModuleLocation;
|
||||
import help.validator.model.IMG;
|
||||
import util.CollectionUtils;
|
||||
|
||||
public class UnusedHelpImageFileFinder {
|
||||
|
||||
private static final String HELP_PATHS_OPTION = "-hp"; // taken from GHelpBuilder
|
||||
private static final String DEBUG_SWITCH = "-debug";
|
||||
|
||||
private static List<String> moduleHelpPaths;
|
||||
private static List<String> moduleHelpPaths = new ArrayList<>();
|
||||
private static boolean debugEnabled = false;
|
||||
|
||||
private SortedSet<Path> unusedFiles;
|
||||
@ -78,24 +80,20 @@ public class UnusedHelpImageFileFinder {
|
||||
}
|
||||
|
||||
public SortedSet<Path> getUnusedImages() {
|
||||
return new TreeSet<Path>(unusedFiles);
|
||||
return new TreeSet<>(unusedFiles);
|
||||
}
|
||||
|
||||
private static SortedSet<Path> getUnusedFiles(Collection<IMG> referencedIMGs,
|
||||
Collection<Path> imageFiles) {
|
||||
|
||||
Map<Path, IMG> fileToIMGMap = new HashMap<Path, IMG>();
|
||||
Map<Path, IMG> fileToIMGMap = new HashMap<>();
|
||||
for (IMG img : referencedIMGs) {
|
||||
fileToIMGMap.put(img.getImageFile(), img);
|
||||
}
|
||||
|
||||
SortedSet<Path> set = new TreeSet<Path>(new Comparator<Path>() {
|
||||
@Override
|
||||
public int compare(Path f1, Path f2) {
|
||||
return f1.toUri().toString().toLowerCase().compareTo(
|
||||
f2.toUri().toString().toLowerCase());
|
||||
}
|
||||
});
|
||||
SortedSet<Path> set =
|
||||
new TreeSet<>((f1, f2) -> f1.toUri().toString().toLowerCase().compareTo(
|
||||
f2.toUri().toString().toLowerCase()));
|
||||
for (Path file : imageFiles) {
|
||||
IMG img = fileToIMGMap.get(file);
|
||||
if (img == null && !isExcludedImageFile(file)) {
|
||||
@ -111,8 +109,9 @@ public class UnusedHelpImageFileFinder {
|
||||
return absolutePath.indexOf("help/shared/") != -1;
|
||||
}
|
||||
|
||||
private static Collection<IMG> getReferencedIMGs(Collection<HelpModuleLocation> helpCollections) {
|
||||
Set<IMG> set = new HashSet<IMG>();
|
||||
private static Collection<IMG> getReferencedIMGs(
|
||||
Collection<HelpModuleLocation> helpCollections) {
|
||||
Set<IMG> set = new HashSet<>();
|
||||
for (HelpModuleLocation help : helpCollections) {
|
||||
Collection<IMG> IMGs = help.getAllIMGs();
|
||||
set.addAll(IMGs);
|
||||
@ -122,7 +121,7 @@ public class UnusedHelpImageFileFinder {
|
||||
|
||||
private static Collection<Path> getAllImagesOnDisk(
|
||||
Collection<HelpModuleLocation> helpDirectories) {
|
||||
List<Path> files = new ArrayList<Path>();
|
||||
List<Path> files = new ArrayList<>();
|
||||
for (HelpModuleLocation help : helpDirectories) {
|
||||
Path helpDir = help.getHelpLocation();
|
||||
gatherImageFiles(helpDir, files);
|
||||
@ -155,10 +154,10 @@ public class UnusedHelpImageFileFinder {
|
||||
|
||||
private static List<HelpModuleLocation> collectHelp() {
|
||||
debug("Parsing help dirs...");
|
||||
List<HelpModuleLocation> helpCollections =
|
||||
new ArrayList<HelpModuleLocation>(moduleHelpPaths.size());
|
||||
List<HelpModuleLocation> helpCollections = new ArrayList<>(moduleHelpPaths.size());
|
||||
for (String helpDirName : moduleHelpPaths) {
|
||||
// 1) Make sure the help directory exists
|
||||
|
||||
// Make sure the help directory exists
|
||||
File helpDirectoryFile = null;
|
||||
try {
|
||||
helpDirectoryFile = new File(helpDirName).getCanonicalFile();
|
||||
@ -172,14 +171,8 @@ public class UnusedHelpImageFileFinder {
|
||||
errorMessage("Help directory not found - skipping: " + helpDirName);
|
||||
continue;
|
||||
}
|
||||
File moduleDir = helpDirectoryFile.getParentFile();
|
||||
File manifestFile = new File(moduleDir, "Module.manifest");
|
||||
if (!manifestFile.exists()) {
|
||||
errorMessage("Help directory not inside valid module: " + helpDirName);
|
||||
continue;
|
||||
}
|
||||
|
||||
// 3) Create the help directory
|
||||
// Create the help directory
|
||||
helpCollections.add(HelpBuildUtils.toLocation(helpDirectoryFile));
|
||||
}
|
||||
|
||||
@ -188,8 +181,8 @@ public class UnusedHelpImageFileFinder {
|
||||
|
||||
private static void debug(String string) {
|
||||
if (debugEnabled) {
|
||||
System.out.println("[" + UnusedHelpImageFileFinder.class.getSimpleName() + "] " +
|
||||
string);
|
||||
System.out.println(
|
||||
"[" + UnusedHelpImageFileFinder.class.getSimpleName() + "] " + string);
|
||||
}
|
||||
}
|
||||
|
||||
@ -197,7 +190,7 @@ public class UnusedHelpImageFileFinder {
|
||||
StringBuilder buffy = new StringBuilder();
|
||||
|
||||
errorMessage("Usage:\n");
|
||||
buffy.append("<module help path1[;module help path2;module help path3;...]> [-debug]");
|
||||
buffy.append("-hp path1[-hp path2 -hp path3 ...]> [-debug]");
|
||||
|
||||
errorMessage(buffy.toString());
|
||||
}
|
||||
@ -209,23 +202,53 @@ public class UnusedHelpImageFileFinder {
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
List<String> argList = Arrays.asList(args);
|
||||
|
||||
// get module directory paths
|
||||
String modulePathsString = argList.get(args.length - 1);
|
||||
moduleHelpPaths = new ArrayList<String>();
|
||||
StringTokenizer tokenizer = new StringTokenizer(modulePathsString, File.pathSeparator);
|
||||
while (tokenizer.hasMoreTokens()) {
|
||||
moduleHelpPaths.add(tokenizer.nextToken());
|
||||
List<String> argList = CollectionUtils.asList(args);
|
||||
int debugIndex = argList.indexOf(DEBUG_SWITCH);
|
||||
if (debugIndex > -1) {
|
||||
debugEnabled = true;
|
||||
argList.remove(debugIndex);
|
||||
}
|
||||
if (moduleHelpPaths.size() == 0) {
|
||||
errorMessage("Missing molule help path(s) argument - it must be last in the arg list");
|
||||
|
||||
Map<Integer, String> mapped = new TreeMap<>();
|
||||
for (int i = 0; i < argList.size(); i++) {
|
||||
mapped.put(i, argList.get(i));
|
||||
}
|
||||
|
||||
for (int i = 0; i < argList.size(); i++) {
|
||||
String opt = argList.get(i);
|
||||
if (opt.equals(HELP_PATHS_OPTION)) {
|
||||
|
||||
if (i >= argList.size()) {
|
||||
errorMessage(HELP_PATHS_OPTION + " requires an argument");
|
||||
printUsage();
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
int debugIndex = argList.indexOf(DEBUG_SWITCH);
|
||||
debugEnabled = debugIndex != -1;
|
||||
mapped.remove(i);
|
||||
String paths = mapped.remove(++i);
|
||||
if (StringUtils.isBlank(paths)) {
|
||||
errorMessage(HELP_PATHS_OPTION + " requires an argument");
|
||||
printUsage();
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
// each entry should be just one value, but handle multiple paths anyway
|
||||
for (String p : paths.split(File.pathSeparator)) {
|
||||
moduleHelpPaths.add(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (moduleHelpPaths.size() == 0) {
|
||||
errorMessage(
|
||||
"Missing molule help path(s) arguments - actual arguments:\n\t'" + argList + "'");
|
||||
printUsage();
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
if (!mapped.isEmpty()) {
|
||||
errorMessage("Ignoring unknown arguments: " + mapped.values());
|
||||
}
|
||||
}
|
||||
|
||||
private static void errorMessage(String message) {
|
||||
@ -233,7 +256,7 @@ public class UnusedHelpImageFileFinder {
|
||||
}
|
||||
|
||||
private static void errorMessage(String message, Throwable t) {
|
||||
System.err.println("[" + GHelpBuilder.class.getSimpleName() + "] " + message);
|
||||
System.err.println("[" + UnusedHelpImageFileFinder.class.getSimpleName() + "] " + message);
|
||||
if (t != null) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
|
@ -0,0 +1,32 @@
|
||||
/* ###
|
||||
* 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 help.validator.links;
|
||||
|
||||
import help.validator.model.IMG;
|
||||
|
||||
/**
|
||||
* A link that represents the case where the HTML tried to reference a runtime Java image, but
|
||||
* that value is not found
|
||||
*/
|
||||
public class InvalidRuntimeIMGFileInvalidLink extends InvalidIMGLink {
|
||||
|
||||
private static final String MESSAGE =
|
||||
"Runtime image not found (e.g., Icons.XYZ_ICON not found)";
|
||||
|
||||
public InvalidRuntimeIMGFileInvalidLink(IMG img) {
|
||||
super(img, MESSAGE);
|
||||
}
|
||||
}
|
@ -79,6 +79,10 @@ public class IMG implements Comparable<IMG> {
|
||||
return imageLocation.isRuntime();
|
||||
}
|
||||
|
||||
public boolean isInvalid() {
|
||||
return imageLocation.isInvalidRuntimeImage();
|
||||
}
|
||||
|
||||
public Path getImageFile() {
|
||||
return imgFile;
|
||||
}
|
||||
|
@ -141,6 +141,38 @@ task buildHelp(type: JavaExec, dependsOn: indexHelp) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Task for finding unused images that are not referenced from Ghidra help files
|
||||
task findUnusedHelp(type: JavaExec) {
|
||||
group rootProject.GHIDRA_GROUP
|
||||
description " Finds unused help images for this module. [gradle/helpProject.gradle]\n"
|
||||
|
||||
File helpRootDir = file('src/main/help/help')
|
||||
File outputDir = file('build/help/main/help')
|
||||
|
||||
dependsOn configurations.helpPath
|
||||
|
||||
inputs.dir helpRootDir
|
||||
|
||||
classpath = sourceSets.helpIndex.runtimeClasspath
|
||||
|
||||
main = 'help.validator.UnusedHelpImageFileFinder'
|
||||
|
||||
args '-debug' // print debug info
|
||||
|
||||
doFirst {
|
||||
// this modules runtime classpath (contains jhall.jar)
|
||||
classpath project(':Help').sourceSets.main.runtimeClasspath
|
||||
|
||||
// the current help dir to process
|
||||
args "-hp"
|
||||
args "${helpRootDir.absolutePath}"
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// include the help into the module's jar
|
||||
jar {
|
||||
from "build/help/main" // include the generated help index files
|
||||
|
Loading…
Reference in New Issue
Block a user