Skip to content

Commit

Permalink
Add Java 9+ module support
Browse files Browse the repository at this point in the history
  • Loading branch information
emmanue1 committed Jun 1, 2019
1 parent 25b7e53 commit fbc5b14
Show file tree
Hide file tree
Showing 14 changed files with 347 additions and 81 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public TreeNodeFactory get(Container.Entry entry) {
}

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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public boolean accept(API api, Path rootPath) {
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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,9 @@ protected <T extends JComponent & UriGettable> T load(API api, File file, Path r
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;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,43 +122,47 @@ public void enterPackageDeclaration(JavaParser.PackageDeclarationContext ctx) {

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);
if ((length == 0) || (sbTypeDeclaration.charAt(length - 1) == '/')) {
sbTypeDeclaration.append(typeName);
} else {
sbTypeDeclaration.append('$').append(typeName);
}

HashSet<String> superInternalTypeNameSet = new HashSet<>();
String internalTypeName = sbTypeDeclaration.toString();
typeDeclarationSet.add(internalTypeName);
nameToInternalTypeName.put(typeName, internalTypeName);

// Add super type reference
JavaParser.TypeContext superType = ctx.getRuleContext(JavaParser.TypeContext.class, 0);
if (superType != null) {
String superQualifiedTypeName = resolveInternalTypeName(superType.classOrInterfaceType().Identifier());
HashSet<String> superInternalTypeNameSet = new HashSet<>();

if (superQualifiedTypeName.charAt(0) != '*')
superInternalTypeNameSet.add(superQualifiedTypeName);
}
// 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());
// 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 (superQualifiedInterfaceName.charAt(0) != '*')
superInternalTypeNameSet.add(superQualifiedInterfaceName);
}
}
}

if (! superInternalTypeNameSet.isEmpty()) {
superTypeNamesMap.put(internalTypeName, superInternalTypeNameSet);
if (!superInternalTypeNameSet.isEmpty()) {
superTypeNamesMap.put(internalTypeName, superInternalTypeNameSet);
}
}
}

Expand Down Expand Up @@ -197,19 +201,31 @@ public void enterConstDeclaration(JavaParser.ConstDeclarationContext ctx) {

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) {
Expand Down Expand Up @@ -282,15 +298,18 @@ protected TerminalNode getToken(List<ParseTree> children, int i, int type) {
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);
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
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"));
Expand All @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,10 @@ public <T extends JComponent & UriGettable> T makePage(API a, Container.Entry e)

@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();
Expand Down
Original file line number Diff line number Diff line change
@@ -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();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,8 @@ protected String resolveInternalTypeName(List<TerminalNode> identifiers) {
typeNameCache.put(name, qualifiedName);
return qualifiedName;
}
} catch (ClassNotFoundException e) {
assert ExceptionUtil.printStackTrace(e);
} catch (ClassNotFoundException ignore) {
// Ignore class loading error
}

// Type not found
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,23 +171,21 @@ public void setCaretPositionAndCenter(DocumentRange range) {

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);
}
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@ public void decompile(Map<String, String> preferences) {

// Decompile class file
DECOMPILER.decompile(loader, printer, entryInternalName, configuration);
setText(printer.getStringBuffer().toString());
} catch (Throwable t) {
assert ExceptionUtil.printStackTrace(t);
setText("// INTERNAL ERROR //");
Expand Down Expand Up @@ -154,6 +153,11 @@ public void start(int maxLineNumber, int majorVersion, int minorVersion) {
}
}

@Override
public void end() {
setText(stringBuffer.toString());
}

// --- Add strings --- //
@Override
public void printStringConstant(String constant, String ownerInternalName) {
Expand Down
Loading

0 comments on commit fbc5b14

Please sign in to comment.