mirror of
https://github.com/java-decompiler/jd-gui.git
synced 2024-11-26 22:10:22 +00:00
Add Java 9+ module support
This commit is contained in:
parent
25b7e53c02
commit
fbc5b14d66
@ -43,7 +43,7 @@ public class TreeNodeFactoryService {
|
||||
}
|
||||
|
||||
protected TreeNodeFactory get(String containerType, Container.Entry entry) {
|
||||
String path = entry.getPath();;
|
||||
String path = entry.getPath();
|
||||
String type = entry.isDirectory() ? "dir" : "file";
|
||||
String prefix = containerType + ':' + type + ':';
|
||||
TreeNodeFactory factory = null;
|
||||
|
@ -26,7 +26,7 @@ public class JmodContainerFactoryProvider implements ContainerFactory {
|
||||
if (rootPath.toUri().toString().toLowerCase().endsWith(".jmod!/")) {
|
||||
return true;
|
||||
} else {
|
||||
// Extension: accept uncompressed WAR file containing a folder 'WEB-INF'
|
||||
// Extension: accept uncompressed JMOD file containing a folder 'classes'
|
||||
try {
|
||||
return rootPath.getFileSystem().provider().getScheme().equals("file") && Files.exists(rootPath.resolve("classes"));
|
||||
} catch (InvalidPathException e) {
|
||||
|
@ -44,8 +44,9 @@ public abstract class AbstractFileLoaderProvider implements FileLoader {
|
||||
TreeNodeFactory treeNodeFactory = api.getTreeNodeFactory(parentEntry);
|
||||
Object data = (treeNodeFactory != null) ? treeNodeFactory.make(api, parentEntry).getUserObject() : null;
|
||||
Icon icon = (data instanceof TreeNodeData) ? ((TreeNodeData)data).getIcon() : null;
|
||||
String location = file.getPath();
|
||||
|
||||
api.addPanel(file.getName(), icon, "Location: " + file.getAbsolutePath(), mainPanel);
|
||||
api.addPanel(file.getName(), icon, "Location: " + location, mainPanel);
|
||||
return mainPanel;
|
||||
}
|
||||
}
|
||||
|
@ -122,43 +122,47 @@ public class JavaFileIndexerProvider extends AbstractIndexerProvider {
|
||||
|
||||
protected void enterTypeDeclaration(ParserRuleContext ctx) {
|
||||
// Add type declaration
|
||||
String typeName = ctx.getToken(JavaParser.Identifier, 0).getText();
|
||||
int length = sbTypeDeclaration.length();
|
||||
TerminalNode identifier = ctx.getToken(JavaParser.Identifier, 0);
|
||||
|
||||
if ((length == 0) || (sbTypeDeclaration.charAt(length-1) == '/')) {
|
||||
sbTypeDeclaration.append(typeName);
|
||||
} else {
|
||||
sbTypeDeclaration.append('$').append(typeName);
|
||||
}
|
||||
if (identifier != null) {
|
||||
String typeName = identifier.getText();
|
||||
int length = sbTypeDeclaration.length();
|
||||
|
||||
String internalTypeName = sbTypeDeclaration.toString();
|
||||
typeDeclarationSet.add(internalTypeName);
|
||||
nameToInternalTypeName.put(typeName, internalTypeName);
|
||||
|
||||
HashSet<String> superInternalTypeNameSet = new HashSet<>();
|
||||
|
||||
// Add super type reference
|
||||
JavaParser.TypeContext superType = ctx.getRuleContext(JavaParser.TypeContext.class, 0);
|
||||
if (superType != null) {
|
||||
String superQualifiedTypeName = resolveInternalTypeName(superType.classOrInterfaceType().Identifier());
|
||||
|
||||
if (superQualifiedTypeName.charAt(0) != '*')
|
||||
superInternalTypeNameSet.add(superQualifiedTypeName);
|
||||
}
|
||||
|
||||
// Add implementation references
|
||||
JavaParser.TypeListContext superInterfaces = ctx.getRuleContext(JavaParser.TypeListContext.class, 0);
|
||||
if (superInterfaces != null) {
|
||||
for (JavaParser.TypeContext superInterface : superInterfaces.type()) {
|
||||
String superQualifiedInterfaceName = resolveInternalTypeName(superInterface.classOrInterfaceType().Identifier());
|
||||
|
||||
if (superQualifiedInterfaceName.charAt(0) != '*')
|
||||
superInternalTypeNameSet.add(superQualifiedInterfaceName);
|
||||
if ((length == 0) || (sbTypeDeclaration.charAt(length - 1) == '/')) {
|
||||
sbTypeDeclaration.append(typeName);
|
||||
} else {
|
||||
sbTypeDeclaration.append('$').append(typeName);
|
||||
}
|
||||
}
|
||||
|
||||
if (! superInternalTypeNameSet.isEmpty()) {
|
||||
superTypeNamesMap.put(internalTypeName, superInternalTypeNameSet);
|
||||
String internalTypeName = sbTypeDeclaration.toString();
|
||||
typeDeclarationSet.add(internalTypeName);
|
||||
nameToInternalTypeName.put(typeName, internalTypeName);
|
||||
|
||||
HashSet<String> superInternalTypeNameSet = new HashSet<>();
|
||||
|
||||
// Add super type reference
|
||||
JavaParser.TypeContext superType = ctx.getRuleContext(JavaParser.TypeContext.class, 0);
|
||||
if (superType != null) {
|
||||
String superQualifiedTypeName = resolveInternalTypeName(superType.classOrInterfaceType().Identifier());
|
||||
|
||||
if (superQualifiedTypeName.charAt(0) != '*')
|
||||
superInternalTypeNameSet.add(superQualifiedTypeName);
|
||||
}
|
||||
|
||||
// Add implementation references
|
||||
JavaParser.TypeListContext superInterfaces = ctx.getRuleContext(JavaParser.TypeListContext.class, 0);
|
||||
if (superInterfaces != null) {
|
||||
for (JavaParser.TypeContext superInterface : superInterfaces.type()) {
|
||||
String superQualifiedInterfaceName = resolveInternalTypeName(superInterface.classOrInterfaceType().Identifier());
|
||||
|
||||
if (superQualifiedInterfaceName.charAt(0) != '*')
|
||||
superInternalTypeNameSet.add(superQualifiedInterfaceName);
|
||||
}
|
||||
}
|
||||
|
||||
if (!superInternalTypeNameSet.isEmpty()) {
|
||||
superTypeNamesMap.put(internalTypeName, superInternalTypeNameSet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -197,19 +201,31 @@ public class JavaFileIndexerProvider extends AbstractIndexerProvider {
|
||||
|
||||
public void enterFieldDeclaration(JavaParser.FieldDeclarationContext ctx) {
|
||||
for (JavaParser.VariableDeclaratorContext declaration : ctx.variableDeclarators().variableDeclarator()) {
|
||||
String name = declaration.variableDeclaratorId().Identifier().getText();
|
||||
fieldDeclarationSet.add(name);
|
||||
TerminalNode identifier = declaration.variableDeclaratorId().Identifier();
|
||||
|
||||
if (identifier != null) {
|
||||
String name = identifier.getText();
|
||||
fieldDeclarationSet.add(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void enterMethodDeclaration(JavaParser.MethodDeclarationContext ctx) {
|
||||
String name = ctx.Identifier().getText();
|
||||
methodDeclarationSet.add(name);
|
||||
TerminalNode identifier = ctx.Identifier();
|
||||
|
||||
if (identifier != null) {
|
||||
String name = identifier.getText();
|
||||
methodDeclarationSet.add(name);
|
||||
}
|
||||
}
|
||||
|
||||
public void enterInterfaceMethodDeclaration(JavaParser.InterfaceMethodDeclarationContext ctx) {
|
||||
String name = ctx.Identifier().getText();
|
||||
methodDeclarationSet.add(name);
|
||||
TerminalNode identifier = ctx.Identifier();
|
||||
|
||||
if (identifier != null) {
|
||||
String name = identifier.getText();
|
||||
methodDeclarationSet.add(name);
|
||||
}
|
||||
}
|
||||
|
||||
public void enterConstructorDeclaration(JavaParser.ConstructorDeclarationContext ctx) {
|
||||
@ -282,15 +298,18 @@ public class JavaFileIndexerProvider extends AbstractIndexerProvider {
|
||||
protected TerminalNode getRightTerminalNode(ParseTree pt) {
|
||||
if (pt instanceof ParserRuleContext) {
|
||||
List<ParseTree> children = ((ParserRuleContext)pt).children;
|
||||
int size = children.size();
|
||||
|
||||
if (size > 0) {
|
||||
ParseTree last = children.get(size - 1);
|
||||
if (children != null) {
|
||||
int size = children.size();
|
||||
|
||||
if (last instanceof TerminalNode) {
|
||||
return (TerminalNode) last;
|
||||
} else {
|
||||
return getRightTerminalNode(last);
|
||||
if (size > 0) {
|
||||
ParseTree last = children.get(size - 1);
|
||||
|
||||
if (last instanceof TerminalNode) {
|
||||
return (TerminalNode) last;
|
||||
} else {
|
||||
return getRightTerminalNode(last);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ import java.io.EOFException;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class ClassFileTreeNodeFactoryProvider extends AbstractTypeFileTreeNodeFactoryProvider {
|
||||
protected static final ImageIcon CLASS_FILE_ICON = new ImageIcon(ClassFileTreeNodeFactoryProvider.class.getClassLoader().getResource("org/jd/gui/images/classf_obj.png"));
|
||||
@ -37,6 +38,15 @@ public class ClassFileTreeNodeFactoryProvider extends AbstractTypeFileTreeNodeFa
|
||||
|
||||
@Override public String[] getSelectors() { return appendSelectors("*:file:*.class"); }
|
||||
|
||||
@Override
|
||||
public Pattern getPathPattern() {
|
||||
if (externalPathPattern == null) {
|
||||
return Pattern.compile("^((?!module-info\\.class).)*$");
|
||||
} else {
|
||||
return externalPathPattern;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends DefaultMutableTreeNode & ContainerEntryGettable & UriGettable> T make(API api, Container.Entry entry) {
|
||||
|
@ -43,10 +43,10 @@ public class JavaFileTreeNodeFactoryProvider extends AbstractTypeFileTreeNodeFac
|
||||
|
||||
@Override
|
||||
public String makeTip(API api, Container.Entry entry) {
|
||||
File file = new File(entry.getContainer().getRoot().getUri());
|
||||
String location = new File(entry.getUri()).getPath();
|
||||
StringBuilder tip = new StringBuilder("<html>Location: ");
|
||||
|
||||
tip.append(file.getPath());
|
||||
tip.append(location);
|
||||
tip.append("</html>");
|
||||
|
||||
return tip.toString();
|
||||
|
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2019 Emmanuel Dupuy.
|
||||
* This project is distributed under the GPLv3 license.
|
||||
* This is a Copyleft license that gives the user the right to use,
|
||||
* copy and modify the code freely for non-commercial purposes.
|
||||
*/
|
||||
|
||||
package org.jd.gui.service.treenode;
|
||||
|
||||
import org.jd.gui.api.API;
|
||||
import org.jd.gui.api.feature.ContainerEntryGettable;
|
||||
import org.jd.gui.api.feature.UriGettable;
|
||||
import org.jd.gui.api.model.Container;
|
||||
import org.jd.gui.util.exception.ExceptionUtil;
|
||||
import org.jd.gui.view.component.ModuleInfoFilePage;
|
||||
import org.jd.gui.view.data.TreeNodeBean;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.tree.DefaultMutableTreeNode;
|
||||
import java.io.File;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class ModuleInfoFileTreeNodeFactoryProvider extends ClassFileTreeNodeFactoryProvider {
|
||||
protected static final Factory FACTORY = new Factory();
|
||||
|
||||
static {
|
||||
// Early class loading
|
||||
try {
|
||||
Class.forName(ModuleInfoFilePage.class.getName());
|
||||
} catch (Exception e) {
|
||||
assert ExceptionUtil.printStackTrace(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override public String[] getSelectors() { return appendSelectors("*:file:*/module-info.class"); }
|
||||
|
||||
@Override public Pattern getPathPattern() { return externalPathPattern; }
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends DefaultMutableTreeNode & ContainerEntryGettable & UriGettable> T make(API api, Container.Entry entry) {
|
||||
int lastSlashIndex = entry.getPath().lastIndexOf('/');
|
||||
String label = entry.getPath().substring(lastSlashIndex+1);
|
||||
return (T)new FileTreeNode(entry, new TreeNodeBean(label, CLASS_FILE_ICON), FACTORY);
|
||||
}
|
||||
|
||||
protected static class Factory implements AbstractTypeFileTreeNodeFactoryProvider.PageAndTipFactory {
|
||||
// --- PageAndTipFactory --- //
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends JComponent & UriGettable> T makePage(API a, Container.Entry e) {
|
||||
return (T)new ModuleInfoFilePage(a, e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String makeTip(API api, Container.Entry entry) {
|
||||
String location = new File(entry.getUri()).getPath();
|
||||
StringBuilder tip = new StringBuilder("<html>Location: ");
|
||||
|
||||
tip.append(location);
|
||||
tip.append("</html>");
|
||||
|
||||
return tip.toString();
|
||||
}
|
||||
}
|
||||
}
|
@ -114,8 +114,8 @@ public abstract class AbstractJavaListener extends JavaBaseListener {
|
||||
typeNameCache.put(name, qualifiedName);
|
||||
return qualifiedName;
|
||||
}
|
||||
} catch (ClassNotFoundException e) {
|
||||
assert ExceptionUtil.printStackTrace(e);
|
||||
} catch (ClassNotFoundException ignore) {
|
||||
// Ignore class loading error
|
||||
}
|
||||
|
||||
// Type not found
|
||||
|
@ -171,23 +171,21 @@ public class AbstractTextPage extends JPanel implements LineNumberNavigable, Con
|
||||
|
||||
if (!foldsExpanded) {
|
||||
try {
|
||||
Rectangle r = textArea.modelToView(start);
|
||||
Rectangle rec = textArea.modelToView(start);
|
||||
|
||||
if (r != null) {
|
||||
if (rec != null) {
|
||||
// Visible
|
||||
setCaretPositionAndCenter(start, end, r);
|
||||
setCaretPositionAndCenter(start, end, rec);
|
||||
} else {
|
||||
// Not visible yet
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
Rectangle r = textArea.modelToView(start);
|
||||
if (r != null) {
|
||||
setCaretPositionAndCenter(start, end, r);
|
||||
}
|
||||
} catch (BadLocationException e) {
|
||||
assert ExceptionUtil.printStackTrace(e);
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
try {
|
||||
Rectangle r = textArea.modelToView(start);
|
||||
if (r != null) {
|
||||
setCaretPositionAndCenter(start, end, r);
|
||||
}
|
||||
} catch (BadLocationException e) {
|
||||
assert ExceptionUtil.printStackTrace(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -84,7 +84,6 @@ public class ClassFilePage extends TypePage {
|
||||
|
||||
// Decompile class file
|
||||
DECOMPILER.decompile(loader, printer, entryInternalName, configuration);
|
||||
setText(printer.getStringBuffer().toString());
|
||||
} catch (Throwable t) {
|
||||
assert ExceptionUtil.printStackTrace(t);
|
||||
setText("// INTERNAL ERROR //");
|
||||
@ -154,6 +153,11 @@ public class ClassFilePage extends TypePage {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void end() {
|
||||
setText(stringBuffer.toString());
|
||||
}
|
||||
|
||||
// --- Add strings --- //
|
||||
@Override
|
||||
public void printStringConstant(String constant, String ownerInternalName) {
|
||||
|
@ -45,46 +45,57 @@ public abstract class CustomLineNumbersPage extends HyperlinkPage {
|
||||
protected int[] lineNumberMap = null;
|
||||
protected int maxLineNumber = 0;
|
||||
|
||||
public void setMaxLineNumber(int maxLineNumber) {
|
||||
protected void setMaxLineNumber(int maxLineNumber) {
|
||||
if (maxLineNumber > 0) {
|
||||
if (lineNumberMap == null) {
|
||||
lineNumberMap = new int[maxLineNumber * 3 / 2];
|
||||
lineNumberMap = new int[maxLineNumber+1];
|
||||
} else if (lineNumberMap.length <= maxLineNumber) {
|
||||
int[] tmp = new int[maxLineNumber * 3 / 2];
|
||||
int[] tmp = new int[maxLineNumber+1];
|
||||
System.arraycopy(lineNumberMap, 0, tmp, 0, lineNumberMap.length);
|
||||
lineNumberMap = tmp;
|
||||
}
|
||||
|
||||
if (this.maxLineNumber < maxLineNumber) {
|
||||
this.maxLineNumber = maxLineNumber;
|
||||
this.maxLineNumber = maxLineNumber;
|
||||
}
|
||||
}
|
||||
|
||||
protected void initLineNumbers() {
|
||||
String text = getText();
|
||||
int len = text.length();
|
||||
|
||||
if (len == 0) {
|
||||
setMaxLineNumber(0);
|
||||
} else {
|
||||
int mln = len - text.replace("\n", "").length();
|
||||
|
||||
if (text.charAt(len-1) != '\n') {
|
||||
mln++;
|
||||
}
|
||||
|
||||
setMaxLineNumber(mln);
|
||||
|
||||
for (int i=1; i<=maxLineNumber; i++) {
|
||||
lineNumberMap[i] = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void initLineNumbers(int maxLineNumber) {
|
||||
setMaxLineNumber(maxLineNumber);
|
||||
|
||||
for (int i=1; i<=maxLineNumber; i++) {
|
||||
lineNumberMap[i] = i;
|
||||
}
|
||||
}
|
||||
|
||||
public void setLineNumber(int textAreaLineNumber, int originalLineNumber) {
|
||||
protected void setLineNumber(int textAreaLineNumber, int originalLineNumber) {
|
||||
if (originalLineNumber > 0) {
|
||||
setMaxLineNumber(textAreaLineNumber);
|
||||
lineNumberMap[textAreaLineNumber] = originalLineNumber;
|
||||
}
|
||||
}
|
||||
|
||||
public void clearLineNumbers() {
|
||||
protected void clearLineNumbers() {
|
||||
if (lineNumberMap != null) {
|
||||
Arrays.fill(lineNumberMap, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public int getMaximumSourceLineNumber() { return maxLineNumber; }
|
||||
protected int getMaximumSourceLineNumber() { return maxLineNumber; }
|
||||
|
||||
public int getTextAreaLineNumber(int originalLineNumber) {
|
||||
protected int getTextAreaLineNumber(int originalLineNumber) {
|
||||
int textAreaLineNumber = 1;
|
||||
int greatestLowerSourceLineNumber = 0;
|
||||
int i = lineNumberMap.length;
|
||||
|
@ -40,12 +40,8 @@ public class JavaFilePage extends TypePage {
|
||||
referenceListener.init(declarationListener);
|
||||
ANTLRJavaParser.parse(new ANTLRInputStream(text), referenceListener);
|
||||
// Display
|
||||
initLineNumbers(getMaxLineNumber(text));
|
||||
setText(text);
|
||||
}
|
||||
|
||||
private static int getMaxLineNumber(String text) {
|
||||
return text.length() - text.replace("\n", "").length();
|
||||
initLineNumbers();
|
||||
}
|
||||
|
||||
public String getSyntaxStyle() { return SyntaxConstants.SYNTAX_STYLE_JAVA; }
|
||||
@ -396,7 +392,7 @@ public class JavaFilePage extends TypePage {
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
} else if (ctx.primary() != null) {
|
||||
TerminalNode identifier = ctx.primary().Identifier();
|
||||
|
||||
if (identifier != null) {
|
||||
|
@ -0,0 +1,160 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2019 Emmanuel Dupuy.
|
||||
* This project is distributed under the GPLv3 license.
|
||||
* This is a Copyleft license that gives the user the right to use,
|
||||
* copy and modify the code freely for non-commercial purposes.
|
||||
*/
|
||||
|
||||
package org.jd.gui.view.component;
|
||||
|
||||
import org.fife.ui.rsyntaxtextarea.*;
|
||||
import org.jd.gui.api.API;
|
||||
import org.jd.gui.api.model.Container;
|
||||
import org.jd.gui.util.decompiler.ContainerLoader;
|
||||
import org.jd.gui.util.exception.ExceptionUtil;
|
||||
|
||||
import javax.swing.text.Segment;
|
||||
import java.util.Map;
|
||||
|
||||
public class ModuleInfoFilePage extends ClassFilePage {
|
||||
public static final String SYNTAX_STYLE_JAVA_MODULE = "text/java-module";
|
||||
|
||||
static {
|
||||
// Add a new token maker for Java 9+ module
|
||||
AbstractTokenMakerFactory atmf = (AbstractTokenMakerFactory)TokenMakerFactory.getDefaultInstance();
|
||||
atmf.putMapping(SYNTAX_STYLE_JAVA_MODULE, ModuleInfoTokenMaker.class.getName());
|
||||
}
|
||||
|
||||
public ModuleInfoFilePage(API api, Container.Entry entry) {
|
||||
super(api, entry);
|
||||
}
|
||||
|
||||
public void decompile(Map<String, String> preferences) {
|
||||
try {
|
||||
// Clear ...
|
||||
clearHyperlinks();
|
||||
clearLineNumbers();
|
||||
typeDeclarations.clear();
|
||||
|
||||
// Init preferences
|
||||
boolean unicodeEscape = getPreferenceValue(preferences, ESCAPE_UNICODE_CHARACTERS, false);
|
||||
|
||||
// Init loader
|
||||
ContainerLoader loader = new ContainerLoader(entry);
|
||||
|
||||
// Init printer
|
||||
ModuleInfoFilePrinter printer = new ModuleInfoFilePrinter();
|
||||
printer.setUnicodeEscape(unicodeEscape);
|
||||
|
||||
// Format internal name
|
||||
String entryPath = entry.getPath();
|
||||
assert entryPath.endsWith(".class");
|
||||
String entryInternalName = entryPath.substring(0, entryPath.length() - 6); // 6 = ".class".length()
|
||||
|
||||
// Decompile class file
|
||||
DECOMPILER.decompile(loader, printer, entryInternalName);
|
||||
} catch (Throwable t) {
|
||||
assert ExceptionUtil.printStackTrace(t);
|
||||
setText("// INTERNAL ERROR //");
|
||||
}
|
||||
}
|
||||
|
||||
public String getSyntaxStyle() { return SYNTAX_STYLE_JAVA_MODULE; }
|
||||
|
||||
public class ModuleInfoFilePrinter extends ClassFilePrinter {
|
||||
@Override
|
||||
public void start(int maxLineNumber, int majorVersion, int minorVersion) {}
|
||||
|
||||
@Override
|
||||
public void end() {
|
||||
setText(stringBuffer.toString());
|
||||
initLineNumbers();
|
||||
}
|
||||
}
|
||||
|
||||
// https://github.com/bobbylight/RSyntaxTextArea/wiki/Adding-Syntax-Highlighting-for-a-new-Language
|
||||
public static class ModuleInfoTokenMaker extends AbstractTokenMaker {
|
||||
@Override
|
||||
public TokenMap getWordsToHighlight() {
|
||||
TokenMap tokenMap = new TokenMap();
|
||||
|
||||
tokenMap.put("exports", Token.RESERVED_WORD);
|
||||
tokenMap.put("module", Token.RESERVED_WORD);
|
||||
tokenMap.put("open", Token.RESERVED_WORD);
|
||||
tokenMap.put("opens", Token.RESERVED_WORD);
|
||||
tokenMap.put("provides", Token.RESERVED_WORD);
|
||||
tokenMap.put("requires", Token.RESERVED_WORD);
|
||||
tokenMap.put("to", Token.RESERVED_WORD);
|
||||
tokenMap.put("transitive", Token.RESERVED_WORD);
|
||||
tokenMap.put("uses", Token.RESERVED_WORD);
|
||||
tokenMap.put("with", Token.RESERVED_WORD);
|
||||
|
||||
return tokenMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addToken(Segment segment, int start, int end, int tokenType, int startOffset) {
|
||||
// This assumes all keywords, etc. were parsed as "identifiers."
|
||||
if (tokenType==Token.IDENTIFIER) {
|
||||
int value = wordsToHighlight.get(segment, start, end);
|
||||
if (value != -1) {
|
||||
tokenType = value;
|
||||
}
|
||||
}
|
||||
super.addToken(segment, start, end, tokenType, startOffset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Token getTokenList(Segment text, int startTokenType, int startOffset) {
|
||||
resetTokenList();
|
||||
|
||||
char[] array = text.array;
|
||||
int offset = text.offset;
|
||||
int end = offset + text.count;
|
||||
|
||||
int newStartOffset = startOffset - offset;
|
||||
|
||||
int currentTokenStart = offset;
|
||||
int currentTokenType = startTokenType;
|
||||
|
||||
for (int i=offset; i<end; i++) {
|
||||
char c = array[i];
|
||||
|
||||
switch (currentTokenType) {
|
||||
case Token.NULL:
|
||||
currentTokenStart = i; // Starting a new token here.
|
||||
if (RSyntaxUtilities.isLetter(c) || c=='_') {
|
||||
currentTokenType = Token.IDENTIFIER;
|
||||
} else {
|
||||
currentTokenType = Token.WHITESPACE;
|
||||
}
|
||||
break;
|
||||
default: // Should never happen
|
||||
case Token.WHITESPACE:
|
||||
if (RSyntaxUtilities.isLetterOrDigit(c) || c=='_') {
|
||||
addToken(text, currentTokenStart, i-1, Token.WHITESPACE, newStartOffset+currentTokenStart);
|
||||
currentTokenStart = i;
|
||||
currentTokenType = Token.IDENTIFIER;
|
||||
}
|
||||
break;
|
||||
case Token.IDENTIFIER:
|
||||
if (!RSyntaxUtilities.isLetterOrDigit(c) && c!='_') {
|
||||
addToken(text, currentTokenStart, i-1, Token.IDENTIFIER, newStartOffset+currentTokenStart);
|
||||
currentTokenStart = i;
|
||||
currentTokenType = Token.WHITESPACE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (currentTokenType == Token.NULL) {
|
||||
addNullToken();
|
||||
}else {
|
||||
addToken(text, currentTokenStart,end-1, currentTokenType, newStartOffset+currentTokenStart);
|
||||
addNullToken();
|
||||
}
|
||||
|
||||
return firstToken;
|
||||
}
|
||||
}
|
||||
}
|
@ -17,6 +17,7 @@ org.jd.gui.service.treenode.JspFileTreeNodeFactoryProvider
|
||||
org.jd.gui.service.treenode.ManifestFileTreeNodeFactoryProvider
|
||||
org.jd.gui.service.treenode.MetainfDirectoryTreeNodeFactoryProvider
|
||||
org.jd.gui.service.treenode.MetainfServiceFileTreeNodeFactoryProvider
|
||||
org.jd.gui.service.treenode.ModuleInfoFileTreeNodeFactoryProvider
|
||||
org.jd.gui.service.treenode.PackageTreeNodeFactoryProvider
|
||||
org.jd.gui.service.treenode.PropertiesFileTreeNodeFactoryProvider
|
||||
org.jd.gui.service.treenode.SqlFileTreeNodeFactoryProvider
|
||||
|
Loading…
Reference in New Issue
Block a user