diff --git a/app/src/main/java/org/jd/gui/controller/SearchInConstantPoolsController.java b/app/src/main/java/org/jd/gui/controller/SearchInConstantPoolsController.java index 8b68fe3a..d0f9701c 100644 --- a/app/src/main/java/org/jd/gui/controller/SearchInConstantPoolsController.java +++ b/app/src/main/java/org/jd/gui/controller/SearchInConstantPoolsController.java @@ -211,10 +211,10 @@ protected HashSet getOuterEntries(Set matching } protected void filter(Indexes indexes, String pattern, int flags, Set matchingEntries) { - boolean declarations = ((flags & SearchInConstantPoolsView.SEARCH_TYPE_DECLARATION) != 0); - boolean references = ((flags & SearchInConstantPoolsView.SEARCH_TYPE_REFERENCE) != 0); + boolean declarations = ((flags & SearchInConstantPoolsView.SEARCH_DECLARATION) != 0); + boolean references = ((flags & SearchInConstantPoolsView.SEARCH_REFERENCE) != 0); - if ((flags & SearchInConstantPoolsView.SEARCH_TYPE_TYPE) != 0) { + if ((flags & SearchInConstantPoolsView.SEARCH_TYPE) != 0) { if (declarations) match(indexes, "typeDeclarations", pattern, SearchInConstantPoolsController::matchTypeEntriesWithChar, @@ -225,7 +225,7 @@ protected void filter(Indexes indexes, String pattern, int flags, Set 0) { String key = String.valueOf(indexes.hashCode()) + "***" + indexName + "***" + pattern; - Map matchedTypes = cache.get(key); + Map matchedEntries = cache.get(key); - if (matchedTypes == null) { + if (matchedEntries == null) { Map index = indexes.getIndex(indexName); if (patternLength == 1) { - matchedTypes = matchWithCharFunction.apply(pattern.charAt(0), index); + matchedEntries = matchWithCharFunction.apply(pattern.charAt(0), index); } else { String lastKey = key.substring(0, key.length() - 1); Map lastMatchedTypes = cache.get(lastKey); if (lastMatchedTypes != null) { - matchedTypes = matchWithStringFunction.apply(pattern, lastMatchedTypes); + matchedEntries = matchWithStringFunction.apply(pattern, lastMatchedTypes); } else { - matchedTypes = matchWithStringFunction.apply(pattern, index); + matchedEntries = matchWithStringFunction.apply(pattern, index); } } // Cache matchingEntries - cache.put(key, matchedTypes); + cache.put(key, matchedEntries); } - if (matchedTypes != null) { - for (Collection entries : matchedTypes.values()) { + if (matchedEntries != null) { + for (Collection entries : matchedEntries.values()) { matchingEntries.addAll(entries); } } @@ -306,7 +317,7 @@ protected void match(Indexes indexes, String indexName, String pattern, protected static Map matchTypeEntriesWithChar(char c, Map index) { if ((c == '*') || (c == '?')) { - return Collections.emptyMap(); + return index; } else { Map map = new HashMap<>(); @@ -345,13 +356,13 @@ protected static Map matchTypeEntriesWithString(String patte protected static Map matchWithChar(char c, Map index) { if ((c == '*') || (c == '?')) { - return Collections.emptyMap(); + return index; } else { Map map = new HashMap<>(); - for (String typeName : index.keySet()) { - if (!typeName.isEmpty() && (typeName.charAt(0) == c)) { - map.put(typeName, index.get(typeName)); + for (String key : index.keySet()) { + if (!key.isEmpty() && (key.charAt(0) == c)) { + map.put(key, index.get(key)); } } @@ -363,9 +374,9 @@ protected static Map matchWithString(String pattern, Map map = new HashMap<>(); - for (String typeName : index.keySet()) { - if (p.matcher(typeName).matches()) { - map.put(typeName, index.get(typeName)); + for (String key : index.keySet()) { + if (p.matcher(key).matches()) { + map.put(key, index.get(key)); } } @@ -419,20 +430,22 @@ protected void onTypeSelected(URI uri, String pattern, int flags) { sbPattern.append(pattern); sbPattern.append("&highlightFlags="); - if ((flags & SearchInConstantPoolsView.SEARCH_TYPE_DECLARATION) != 0) + if ((flags & SearchInConstantPoolsView.SEARCH_DECLARATION) != 0) sbPattern.append('d'); - if ((flags & SearchInConstantPoolsView.SEARCH_TYPE_REFERENCE) != 0) + if ((flags & SearchInConstantPoolsView.SEARCH_REFERENCE) != 0) sbPattern.append('r'); - if ((flags & SearchInConstantPoolsView.SEARCH_TYPE_TYPE) != 0) + if ((flags & SearchInConstantPoolsView.SEARCH_TYPE) != 0) sbPattern.append('t'); - if ((flags & SearchInConstantPoolsView.SEARCH_TYPE_CONSTRUCTOR) != 0) + if ((flags & SearchInConstantPoolsView.SEARCH_CONSTRUCTOR) != 0) sbPattern.append('c'); - if ((flags & SearchInConstantPoolsView.SEARCH_TYPE_METHOD) != 0) + if ((flags & SearchInConstantPoolsView.SEARCH_METHOD) != 0) sbPattern.append('m'); - if ((flags & SearchInConstantPoolsView.SEARCH_TYPE_FIELD) != 0) + if ((flags & SearchInConstantPoolsView.SEARCH_FIELD) != 0) sbPattern.append('f'); - if ((flags & SearchInConstantPoolsView.SEARCH_TYPE_STRING) != 0) + if ((flags & SearchInConstantPoolsView.SEARCH_STRING) != 0) sbPattern.append('s'); + if ((flags & SearchInConstantPoolsView.SEARCH_MODULE) != 0) + sbPattern.append('M'); // TODO In a future release, add 'highlightScope' to display search results in correct type and inner-type // def type = TypeFactoryService.instance.get(entry)?.make(api, entry, null) diff --git a/app/src/main/java/org/jd/gui/util/net/UriUtil.java b/app/src/main/java/org/jd/gui/util/net/UriUtil.java index db7636d6..7fd57ecb 100644 --- a/app/src/main/java/org/jd/gui/util/net/UriUtil.java +++ b/app/src/main/java/org/jd/gui/util/net/UriUtil.java @@ -26,24 +26,25 @@ public class UriUtil { * file://codebase/a/b/c/D$E.class => file://codebase/a/b/c/D.class#typeDeclaration=D$E */ public static URI createURI(API api, Collection> collectionOfFutureIndexes, Container.Entry entry, String query, String fragment) { - TypeFactory typeFactory = TypeFactoryService.getInstance().get(entry); + URI uri = entry.getUri(); - if (typeFactory != null) { - Type type = typeFactory.make(api, entry, fragment); + try { + String path = uri.getPath(); + TypeFactory typeFactory = TypeFactoryService.getInstance().get(entry); - if (type != null) { - URI uri = entry.getUri(); - String path = getOuterPath(collectionOfFutureIndexes, entry, type); + if (typeFactory != null) { + Type type = typeFactory.make(api, entry, fragment); - try { - return new URI(uri.getScheme(), uri.getHost(), path, query, fragment); - } catch (URISyntaxException e) { - assert ExceptionUtil.printStackTrace(e); + if (type != null) { + path = getOuterPath(collectionOfFutureIndexes, entry, type); } } - } - return null; + return new URI(uri.getScheme(), uri.getHost(), path, query, fragment); + } catch (URISyntaxException e) { + assert ExceptionUtil.printStackTrace(e); + return uri; + } } @SuppressWarnings("unchecked") diff --git a/app/src/main/java/org/jd/gui/view/SearchInConstantPoolsView.java b/app/src/main/java/org/jd/gui/view/SearchInConstantPoolsView.java index 8bceaac2..d6f4de82 100644 --- a/app/src/main/java/org/jd/gui/view/SearchInConstantPoolsView.java +++ b/app/src/main/java/org/jd/gui/view/SearchInConstantPoolsView.java @@ -36,13 +36,14 @@ public class SearchInConstantPoolsView { protected static final ContainerComparator CONTAINER_COMPARATOR = new ContainerComparator(); - public static final int SEARCH_TYPE_TYPE = 1; - public static final int SEARCH_TYPE_CONSTRUCTOR = 2; - public static final int SEARCH_TYPE_METHOD = 4; - public static final int SEARCH_TYPE_FIELD = 8; - public static final int SEARCH_TYPE_STRING = 16; - public static final int SEARCH_TYPE_DECLARATION = 32; - public static final int SEARCH_TYPE_REFERENCE = 64; + public static final int SEARCH_TYPE = 1; + public static final int SEARCH_CONSTRUCTOR = 2; + public static final int SEARCH_METHOD = 4; + public static final int SEARCH_FIELD = 8; + public static final int SEARCH_STRING = 16; + public static final int SEARCH_MODULE = 32; + public static final int SEARCH_DECLARATION = 64; + public static final int SEARCH_REFERENCE = 128; protected API api; protected Set accepted = new HashSet<>(); @@ -56,6 +57,7 @@ public class SearchInConstantPoolsView pageChanged()); - setLayout(new BorderLayout()); + setLayout(new BorderLayout()); - JSplitPane splitter = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, new JScrollPane(tree), tabbedPanel); + JSplitPane splitter = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, new JScrollPane(tree), tabbedPanel); splitter.setResizeWeight(0.2); add(splitter, BorderLayout.CENTER); @@ -230,15 +230,28 @@ protected

void pageChanged() { public boolean openUri(URI uri) { try { URI baseUri = new URI(uri.getScheme(), uri.getHost(), uri.getPath(), null); - DefaultMutableTreeNode baseNode = searchTreeNode(baseUri, (DefaultMutableTreeNode)tree.getModel().getRoot()); - if ((baseNode != null) && showPage(uri, baseUri, baseNode)) { - DefaultMutableTreeNode node = searchTreeNode(uri, baseNode); + if (this.uri.equals(baseUri)) { + return true; + } else { + DefaultMutableTreeNode node = searchTreeNode(baseUri, (DefaultMutableTreeNode) tree.getModel().getRoot()); + + if (showPage(uri, baseUri, node)) { + DefaultMutableTreeNode childNode = searchTreeNode(uri, node); + if (childNode != null) { + node = childNode; + } + } if (node != null) { try { // Disable tree node changed listener treeNodeChangedEnabled = false; + // Populate and expand node + if (!(node instanceof PageCreator) && (node instanceof TreeNodeExpandable)) { + ((TreeNodeExpandable) node).populateTreeNode(api); + tree.expandPath(new TreePath(node.getPath())); + } // Select tree node TreePath treePath = new TreePath(node.getPath()); tree.setSelectionPath(treePath); @@ -247,8 +260,8 @@ public boolean openUri(URI uri) { // Enable tree node changed listener treeNodeChangedEnabled = true; } + return true; } - return true; } } catch (URISyntaxException e) { assert ExceptionUtil.printStackTrace(e); diff --git a/services/src/main/java/org/jd/gui/model/container/JmodContainer.java b/services/src/main/java/org/jd/gui/model/container/JavaModuleContainer.java similarity index 76% rename from services/src/main/java/org/jd/gui/model/container/JmodContainer.java rename to services/src/main/java/org/jd/gui/model/container/JavaModuleContainer.java index 4d274979..7c5aa597 100644 --- a/services/src/main/java/org/jd/gui/model/container/JmodContainer.java +++ b/services/src/main/java/org/jd/gui/model/container/JavaModuleContainer.java @@ -12,8 +12,8 @@ import java.nio.file.Path; -public class JmodContainer extends GenericContainer { - public JmodContainer(API api, Container.Entry parentEntry, Path rootPath) { +public class JavaModuleContainer extends GenericContainer { + public JavaModuleContainer(API api, Container.Entry parentEntry, Path rootPath) { super(api, parentEntry, rootPath); } diff --git a/services/src/main/java/org/jd/gui/service/container/JmodContainerFactoryProvider.java b/services/src/main/java/org/jd/gui/service/container/JavaModuleContainerFactoryProvider.java similarity index 86% rename from services/src/main/java/org/jd/gui/service/container/JmodContainerFactoryProvider.java rename to services/src/main/java/org/jd/gui/service/container/JavaModuleContainerFactoryProvider.java index 24e37de2..bbd7229a 100644 --- a/services/src/main/java/org/jd/gui/service/container/JmodContainerFactoryProvider.java +++ b/services/src/main/java/org/jd/gui/service/container/JavaModuleContainerFactoryProvider.java @@ -9,7 +9,7 @@ import org.jd.gui.api.API; import org.jd.gui.api.model.Container; -import org.jd.gui.model.container.JmodContainer; +import org.jd.gui.model.container.JavaModuleContainer; import org.jd.gui.spi.ContainerFactory; import org.jd.gui.util.exception.ExceptionUtil; @@ -17,7 +17,7 @@ import java.nio.file.InvalidPathException; import java.nio.file.Path; -public class JmodContainerFactoryProvider implements ContainerFactory { +public class JavaModuleContainerFactoryProvider implements ContainerFactory { @Override public String getType() { return "jmod"; } @@ -38,6 +38,6 @@ public boolean accept(API api, Path rootPath) { @Override public Container make(API api, Container.Entry parentEntry, Path rootPath) { - return new JmodContainer(api, parentEntry, rootPath); + return new JavaModuleContainer(api, parentEntry, rootPath); } } diff --git a/services/src/main/java/org/jd/gui/service/fileloader/JmodFileLoaderProvider.java b/services/src/main/java/org/jd/gui/service/fileloader/JavaModuleFileLoaderProvider.java similarity index 90% rename from services/src/main/java/org/jd/gui/service/fileloader/JmodFileLoaderProvider.java rename to services/src/main/java/org/jd/gui/service/fileloader/JavaModuleFileLoaderProvider.java index 0b02c609..e30eeeec 100644 --- a/services/src/main/java/org/jd/gui/service/fileloader/JmodFileLoaderProvider.java +++ b/services/src/main/java/org/jd/gui/service/fileloader/JavaModuleFileLoaderProvider.java @@ -11,7 +11,7 @@ import java.io.File; -public class JmodFileLoaderProvider extends ZipFileLoaderProvider { +public class JavaModuleFileLoaderProvider extends ZipFileLoaderProvider { protected static final String[] EXTENSIONS = { "jmod" }; @Override public String[] getExtensions() { return EXTENSIONS; } diff --git a/services/src/main/java/org/jd/gui/service/indexer/AbstractIndexerProvider.java b/services/src/main/java/org/jd/gui/service/indexer/AbstractIndexerProvider.java index 0f6811ea..3794be48 100644 --- a/services/src/main/java/org/jd/gui/service/indexer/AbstractIndexerProvider.java +++ b/services/src/main/java/org/jd/gui/service/indexer/AbstractIndexerProvider.java @@ -77,10 +77,10 @@ protected String[] appendSelectors(String... selectors) { } } - public Pattern getPathPattern() { return externalPathPattern; } + @Override public Pattern getPathPattern() { return externalPathPattern; } @SuppressWarnings("unchecked") - protected static void addToIndex(Indexes indexes, String indexName, Set set, Container.Entry entry) { + protected static void addToIndexes(Indexes indexes, String indexName, Set set, Container.Entry entry) { if (set.size() > 0) { Map index = indexes.getIndex(indexName); diff --git a/services/src/main/java/org/jd/gui/service/indexer/ClassFileIndexerProvider.java b/services/src/main/java/org/jd/gui/service/indexer/ClassFileIndexerProvider.java index 5a8978c7..4a3ce8c3 100644 --- a/services/src/main/java/org/jd/gui/service/indexer/ClassFileIndexerProvider.java +++ b/services/src/main/java/org/jd/gui/service/indexer/ClassFileIndexerProvider.java @@ -19,6 +19,9 @@ import java.util.Collection; import java.util.HashSet; import java.util.Map; +import java.util.regex.Pattern; + +import static org.objectweb.asm.ClassReader.*; /** * Unsafe thread implementation of class file indexer. @@ -36,13 +39,20 @@ public class ClassFileIndexerProvider extends AbstractIndexerProvider { protected HashSet superTypeNameSet = new HashSet<>(); protected HashSet descriptorSet = new HashSet<>(); - protected ClassIndexer classIndexer = new ClassIndexer( - typeDeclarationSet, constructorDeclarationSet, methodDeclarationSet, - fieldDeclarationSet, typeReferenceSet, superTypeNameSet, descriptorSet); - protected SignatureIndexer signatureIndexer = new SignatureIndexer(typeReferenceSet); + protected ClassIndexer classIndexer = new ClassIndexer(); + protected SignatureIndexer signatureIndexer = new SignatureIndexer(); @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 void index(API api, Container.Entry entry, Indexes indexes) { @@ -62,7 +72,7 @@ public void index(API api, Container.Entry entry, Indexes indexes) { try (InputStream inputStream = entry.getInputStream()) { // Index field, method, interfaces & super type ClassReader classReader = new ClassReader(inputStream); - classReader.accept(classIndexer, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES); + classReader.accept(classIndexer, SKIP_CODE|SKIP_DEBUG|SKIP_FRAMES); // Index descriptors for (String descriptor : descriptorSet) { @@ -124,15 +134,15 @@ public void index(API api, Container.Entry entry, Indexes indexes) { String typeName = classIndexer.name; // Append sets to indexes - addToIndex(indexes, "typeDeclarations", typeDeclarationSet, entry); - addToIndex(indexes, "constructorDeclarations", constructorDeclarationSet, entry); - addToIndex(indexes, "methodDeclarations", methodDeclarationSet, entry); - addToIndex(indexes, "fieldDeclarations", fieldDeclarationSet, entry); - addToIndex(indexes, "typeReferences", typeReferenceSet, entry); - addToIndex(indexes, "constructorReferences", constructorReferenceSet, entry); - addToIndex(indexes, "methodReferences", methodReferenceSet, entry); - addToIndex(indexes, "fieldReferences", fieldReferenceSet, entry); - addToIndex(indexes, "strings", stringSet, entry); + addToIndexes(indexes, "typeDeclarations", typeDeclarationSet, entry); + addToIndexes(indexes, "constructorDeclarations", constructorDeclarationSet, entry); + addToIndexes(indexes, "methodDeclarations", methodDeclarationSet, entry); + addToIndexes(indexes, "fieldDeclarations", fieldDeclarationSet, entry); + addToIndexes(indexes, "typeReferences", typeReferenceSet, entry); + addToIndexes(indexes, "constructorReferences", constructorReferenceSet, entry); + addToIndexes(indexes, "methodReferences", methodReferenceSet, entry); + addToIndexes(indexes, "fieldReferences", fieldReferenceSet, entry); + addToIndexes(indexes, "strings", stringSet, entry); // Populate map [super type name : [sub type name]] if (superTypeNameSet.size() > 0) { @@ -147,40 +157,16 @@ public void index(API api, Container.Entry entry, Indexes indexes) { } } - protected static class ClassIndexer extends ClassVisitor { - protected HashSet typeDeclarationSet; - protected HashSet constructorDeclarationSet; - protected HashSet methodDeclarationSet; - protected HashSet fieldDeclarationSet; - protected HashSet typeReferenceSet; - protected HashSet superTypeNameSet; - protected HashSet descriptorSet; - - protected AnnotationIndexer annotationIndexer; - protected FieldIndexer fieldIndexer; - protected MethodIndexer methodIndexer; + protected class ClassIndexer extends ClassVisitor { + protected AnnotationIndexer annotationIndexer = new AnnotationIndexer(); + protected FieldIndexer fieldIndexer = new FieldIndexer(annotationIndexer); + protected MethodIndexer methodIndexer = new MethodIndexer(annotationIndexer); protected String name; - public ClassIndexer( - HashSet typeDeclarationSet, HashSet constructorDeclarationSet, - HashSet methodDeclarationSet, HashSet fieldDeclarationSet, - HashSet typeReferenceSet, HashSet superTypeNameSet, HashSet descriptorSet) { - super(Opcodes.ASM7); - - this.typeDeclarationSet = typeDeclarationSet; - this.constructorDeclarationSet = constructorDeclarationSet; - this.methodDeclarationSet = methodDeclarationSet; - this.fieldDeclarationSet = fieldDeclarationSet; - this.typeReferenceSet = typeReferenceSet; - this.superTypeNameSet = superTypeNameSet; - this.descriptorSet = descriptorSet; - - this.annotationIndexer = new AnnotationIndexer(descriptorSet); - this.fieldIndexer = new FieldIndexer(descriptorSet, annotationIndexer); - this.methodIndexer = new MethodIndexer(descriptorSet, annotationIndexer); - } + public ClassIndexer() { super(Opcodes.ASM7); } + @Override public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { this.name = name; typeDeclarationSet.add(name); @@ -196,22 +182,26 @@ public void visit(int version, int access, String name, String signature, String } } + @Override public AnnotationVisitor visitAnnotation(String desc, boolean visible) { descriptorSet.add(desc); return annotationIndexer; } + @Override public AnnotationVisitor visitTypeAnnotation(int typeRef, TypePath typePath, String desc, boolean visible) { descriptorSet.add(desc); return annotationIndexer; } + @Override public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) { fieldDeclarationSet.add(name); descriptorSet.add(signature==null ? desc : signature); return fieldIndexer; } + @Override public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { if ("".equals(name)) { constructorDeclarationSet.add(this.name); @@ -230,78 +220,66 @@ public MethodVisitor visitMethod(int access, String name, String desc, String si } } - protected static class SignatureIndexer extends SignatureVisitor { - protected HashSet typeReferenceSet; + protected class SignatureIndexer extends SignatureVisitor { + SignatureIndexer() { super(Opcodes.ASM7); } - SignatureIndexer(HashSet typeReferenceSet) { - super(Opcodes.ASM7); - this.typeReferenceSet = typeReferenceSet; - } - - public void visitClassType(String name) { - typeReferenceSet.add(name); - } + @Override public void visitClassType(String name) { typeReferenceSet.add(name); } } - protected static class AnnotationIndexer extends AnnotationVisitor { - protected HashSet descriptorSet; - - public AnnotationIndexer(HashSet descriptorSet) { - super(Opcodes.ASM7); - this.descriptorSet = descriptorSet; - } + protected class AnnotationIndexer extends AnnotationVisitor { + public AnnotationIndexer() { super(Opcodes.ASM7); } - public void visitEnum(String name, String desc, String value) { - descriptorSet.add(desc); - } + @Override public void visitEnum(String name, String desc, String value) { descriptorSet.add(desc); } + @Override public AnnotationVisitor visitAnnotation(String name, String desc) { descriptorSet.add(desc); return this; } } - protected static class FieldIndexer extends FieldVisitor { - protected HashSet descriptorSet; + protected class FieldIndexer extends FieldVisitor { protected AnnotationIndexer annotationIndexer; - public FieldIndexer(HashSet descriptorSet, AnnotationIndexer annotationInexer) { + public FieldIndexer(AnnotationIndexer annotationIndexer) { super(Opcodes.ASM7); - this.descriptorSet = descriptorSet; - this.annotationIndexer = annotationInexer; + this.annotationIndexer = annotationIndexer; } + @Override public AnnotationVisitor visitAnnotation(String desc, boolean visible) { descriptorSet.add(desc); return annotationIndexer; } + @Override public AnnotationVisitor visitTypeAnnotation(int typeRef, TypePath typePath, String desc, boolean visible) { descriptorSet.add(desc); return annotationIndexer; } } - protected static class MethodIndexer extends MethodVisitor { - protected HashSet descriptorSet; + protected class MethodIndexer extends MethodVisitor { protected AnnotationIndexer annotationIndexer; - public MethodIndexer(HashSet descriptorSet, AnnotationIndexer annotationIndexer) { + public MethodIndexer(AnnotationIndexer annotationIndexer) { super(Opcodes.ASM7); - this.descriptorSet = descriptorSet; this.annotationIndexer = annotationIndexer; } + @Override public AnnotationVisitor visitAnnotation(String desc, boolean visible) { descriptorSet.add(desc); return annotationIndexer; } + @Override public AnnotationVisitor visitTypeAnnotation(int typeRef, TypePath typePath, String desc, boolean visible) { descriptorSet.add(desc); return annotationIndexer; } + @Override public AnnotationVisitor visitParameterAnnotation(int parameter, String desc, boolean visible) { descriptorSet.add(desc); return annotationIndexer; diff --git a/services/src/main/java/org/jd/gui/service/indexer/JavaFileIndexerProvider.java b/services/src/main/java/org/jd/gui/service/indexer/JavaFileIndexerProvider.java index a7acd32f..eaf155d9 100644 --- a/services/src/main/java/org/jd/gui/service/indexer/JavaFileIndexerProvider.java +++ b/services/src/main/java/org/jd/gui/service/indexer/JavaFileIndexerProvider.java @@ -43,15 +43,15 @@ public void index(API api, Container.Entry entry, Indexes indexes) { ANTLRJavaParser.parse(new ANTLRInputStream(inputStream), listener); // Append sets to indexes - addToIndex(indexes, "typeDeclarations", listener.getTypeDeclarationSet(), entry); - addToIndex(indexes, "constructorDeclarations", listener.getConstructorDeclarationSet(), entry); - addToIndex(indexes, "methodDeclarations", listener.getMethodDeclarationSet(), entry); - addToIndex(indexes, "fieldDeclarations", listener.getFieldDeclarationSet(), entry); - addToIndex(indexes, "typeReferences", listener.getTypeReferenceSet(), entry); - addToIndex(indexes, "constructorReferences", listener.getConstructorReferenceSet(), entry); - addToIndex(indexes, "methodReferences", listener.getMethodReferenceSet(), entry); - addToIndex(indexes, "fieldReferences", listener.getFieldReferenceSet(), entry); - addToIndex(indexes, "strings", listener.getStringSet(), entry); + addToIndexes(indexes, "typeDeclarations", listener.getTypeDeclarationSet(), entry); + addToIndexes(indexes, "constructorDeclarations", listener.getConstructorDeclarationSet(), entry); + addToIndexes(indexes, "methodDeclarations", listener.getMethodDeclarationSet(), entry); + addToIndexes(indexes, "fieldDeclarations", listener.getFieldDeclarationSet(), entry); + addToIndexes(indexes, "typeReferences", listener.getTypeReferenceSet(), entry); + addToIndexes(indexes, "constructorReferences", listener.getConstructorReferenceSet(), entry); + addToIndexes(indexes, "methodReferences", listener.getMethodReferenceSet(), entry); + addToIndexes(indexes, "fieldReferences", listener.getFieldReferenceSet(), entry); + addToIndexes(indexes, "strings", listener.getStringSet(), entry); // Populate map [super type name : [sub type name]] Map index = indexes.getIndex("subTypeNames"); diff --git a/services/src/main/java/org/jd/gui/service/indexer/JavaModuleFileIndexerProvider.java b/services/src/main/java/org/jd/gui/service/indexer/JavaModuleFileIndexerProvider.java new file mode 100644 index 00000000..41084238 --- /dev/null +++ b/services/src/main/java/org/jd/gui/service/indexer/JavaModuleFileIndexerProvider.java @@ -0,0 +1,54 @@ +/* + * 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.indexer; + +import org.jd.gui.api.API; +import org.jd.gui.api.model.Container; +import org.jd.gui.api.model.Indexes; +import org.jd.gui.spi.Indexer; + +import java.util.Collection; +import java.util.Map; + +public class JavaModuleFileIndexerProvider extends AbstractIndexerProvider { + + @Override public String[] getSelectors() { return appendSelectors("*:file:*.jmod"); } + + @Override + public void index(API api, Container.Entry entry, Indexes indexes) { + for (Container.Entry e : entry.getChildren()) { + if (e.isDirectory() && e.getPath().equals("classes")) { + Map packageDeclarationIndex = indexes.getIndex("packageDeclarations"); + + // Index module-info, packages and CLASS files + index(api, e, indexes, packageDeclarationIndex); + break; + } + } + } + + protected static void index(API api, Container.Entry entry, Indexes indexes, Map packageDeclarationIndex) { + for (Container.Entry e : entry.getChildren()) { + if (e.isDirectory()) { + String path = e.getPath(); + + if (!path.startsWith("classes/META-INF")) { + packageDeclarationIndex.get(path.substring(8)).add(e); // 8 = "classes/".length() + } + + index(api, e, indexes, packageDeclarationIndex); + } else { + Indexer indexer = api.getIndexer(e); + + if (indexer != null) { + indexer.index(api, e, indexes); + } + } + } + } +} diff --git a/services/src/main/java/org/jd/gui/service/indexer/JavaModuleInfoFileIndexerProvider.java b/services/src/main/java/org/jd/gui/service/indexer/JavaModuleInfoFileIndexerProvider.java new file mode 100644 index 00000000..9f22e107 --- /dev/null +++ b/services/src/main/java/org/jd/gui/service/indexer/JavaModuleInfoFileIndexerProvider.java @@ -0,0 +1,103 @@ +/* + * 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.indexer; + +import org.jd.gui.api.API; +import org.jd.gui.api.model.Container; +import org.jd.gui.api.model.Indexes; +import org.jd.gui.util.exception.ExceptionUtil; +import org.objectweb.asm.*; + +import java.io.InputStream; +import java.util.HashSet; + +import static org.objectweb.asm.ClassReader.*; + +/** + * Unsafe thread implementation of class file indexer. + */ +public class JavaModuleInfoFileIndexerProvider extends AbstractIndexerProvider { + protected HashSet javaModuleDeclarationSet = new HashSet<>(); + protected HashSet javaModuleReferenceSet = new HashSet<>(); + protected HashSet typeReferenceSet = new HashSet<>(); + + protected ClassIndexer classIndexer = new ClassIndexer(); + + @Override public String[] getSelectors() { return appendSelectors("jmod:file:classes/module-info.class"); } + + @Override + @SuppressWarnings("unchecked") + public void index(API api, Container.Entry entry, Indexes indexes) { + // Cleaning sets... + javaModuleDeclarationSet.clear(); + javaModuleReferenceSet.clear(); + typeReferenceSet.clear(); + + try (InputStream inputStream = entry.getInputStream()) { + // Index field, method, interfaces & super type + ClassReader classReader = new ClassReader(inputStream); + classReader.accept(classIndexer, SKIP_CODE|SKIP_DEBUG|SKIP_FRAMES); + + // Append sets to indexes + addToIndexes(indexes, "javaModuleDeclarations", javaModuleDeclarationSet, entry); + addToIndexes(indexes, "javaModuleReferences", javaModuleReferenceSet, entry); + addToIndexes(indexes, "typeReferences", typeReferenceSet, entry); + } catch (Exception e) { + assert ExceptionUtil.printStackTrace(e); + } + } + + protected class ClassIndexer extends ClassVisitor { + protected ModuleIndexer moduleIndexer = new ModuleIndexer(); + + public ClassIndexer() { super(Opcodes.ASM7); } + + @Override + public ModuleVisitor visitModule(String moduleName, int moduleFlags, String moduleVersion) { + javaModuleDeclarationSet.add(moduleName); + return moduleIndexer; + } + } + + protected class ModuleIndexer extends ModuleVisitor { + public ModuleIndexer() { super(Opcodes.ASM7); } + + @Override public void visitMainClass(final String mainClass) { typeReferenceSet.add(mainClass); } + @Override public void visitRequire(final String module, final int access, final String version) { javaModuleReferenceSet.add(module); } + @Override public void visitUse(final String service) { typeReferenceSet.add(service); } + + @Override + public void visitExport(final String packaze, final int access, final String... modules) { + if (modules != null) { + for (String module : modules) { + javaModuleReferenceSet.add(module); + } + } + } + + @Override + public void visitOpen(final String packaze, final int access, final String... modules) { + if (modules != null) { + for (String module : modules) { + javaModuleReferenceSet.add(module); + } + } + } + + @Override + public void visitProvide(final String service, final String... providers) { + typeReferenceSet.add(service); + + if (providers != null) { + for (String provider : providers) { + typeReferenceSet.add(provider); + } + } + } + } +} diff --git a/services/src/main/java/org/jd/gui/service/indexer/ZipFileIndexerProvider.java b/services/src/main/java/org/jd/gui/service/indexer/ZipFileIndexerProvider.java index d544bfa6..6e3ecc73 100644 --- a/services/src/main/java/org/jd/gui/service/indexer/ZipFileIndexerProvider.java +++ b/services/src/main/java/org/jd/gui/service/indexer/ZipFileIndexerProvider.java @@ -14,7 +14,7 @@ public class ZipFileIndexerProvider extends AbstractIndexerProvider { - @Override public String[] getSelectors() { return appendSelectors("*:file:*.zip", "*:file:*.jar", "*:file:*.war", "*:file:*.ear", "*:file:*.aar", "*:file:*.jmod"); } + @Override public String[] getSelectors() { return appendSelectors("*:file:*.zip", "*:file:*.jar", "*:file:*.war", "*:file:*.ear", "*:file:*.aar"); } @Override public void index(API api, Container.Entry entry, Indexes indexes) { diff --git a/services/src/main/java/org/jd/gui/service/treenode/JmodFileTreeNodeFactoryProvider.java b/services/src/main/java/org/jd/gui/service/treenode/JavaModuleFileTreeNodeFactoryProvider.java similarity index 92% rename from services/src/main/java/org/jd/gui/service/treenode/JmodFileTreeNodeFactoryProvider.java rename to services/src/main/java/org/jd/gui/service/treenode/JavaModuleFileTreeNodeFactoryProvider.java index c51cb461..1359e412 100644 --- a/services/src/main/java/org/jd/gui/service/treenode/JmodFileTreeNodeFactoryProvider.java +++ b/services/src/main/java/org/jd/gui/service/treenode/JavaModuleFileTreeNodeFactoryProvider.java @@ -16,7 +16,7 @@ import javax.swing.tree.DefaultMutableTreeNode; import java.io.File; -public class JmodFileTreeNodeFactoryProvider extends ZipFileTreeNodeFactoryProvider { +public class JavaModuleFileTreeNodeFactoryProvider extends ZipFileTreeNodeFactoryProvider { @Override public String[] getSelectors() { return appendSelectors("*:file:*.jmod"); } @Override diff --git a/services/src/main/java/org/jd/gui/service/treenode/JmodPackageTreeNodeFactoryProvider.java b/services/src/main/java/org/jd/gui/service/treenode/JavaModulePackageTreeNodeFactoryProvider.java similarity index 86% rename from services/src/main/java/org/jd/gui/service/treenode/JmodPackageTreeNodeFactoryProvider.java rename to services/src/main/java/org/jd/gui/service/treenode/JavaModulePackageTreeNodeFactoryProvider.java index 4456cdf8..fbd71e57 100644 --- a/services/src/main/java/org/jd/gui/service/treenode/JmodPackageTreeNodeFactoryProvider.java +++ b/services/src/main/java/org/jd/gui/service/treenode/JavaModulePackageTreeNodeFactoryProvider.java @@ -9,7 +9,7 @@ import java.util.regex.Pattern; -public class JmodPackageTreeNodeFactoryProvider extends PackageTreeNodeFactoryProvider { +public class JavaModulePackageTreeNodeFactoryProvider extends PackageTreeNodeFactoryProvider { @Override public String[] getSelectors() { return appendSelectors("jmod:dir:*"); } diff --git a/services/src/main/java/org/jd/gui/service/treenode/ModuleInfoFileTreeNodeFactoryProvider.java b/services/src/main/java/org/jd/gui/service/treenode/ModuleInfoFileTreeNodeFactoryProvider.java index a0ea3707..099d1a67 100644 --- a/services/src/main/java/org/jd/gui/service/treenode/ModuleInfoFileTreeNodeFactoryProvider.java +++ b/services/src/main/java/org/jd/gui/service/treenode/ModuleInfoFileTreeNodeFactoryProvider.java @@ -11,6 +11,8 @@ 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.api.model.Type; +import org.jd.gui.spi.TypeFactory; import org.jd.gui.util.exception.ExceptionUtil; import org.jd.gui.view.component.ModuleInfoFilePage; import org.jd.gui.view.data.TreeNodeBean; @@ -18,9 +20,11 @@ import javax.swing.*; import javax.swing.tree.DefaultMutableTreeNode; import java.io.File; +import java.util.Collection; import java.util.regex.Pattern; public class ModuleInfoFileTreeNodeFactoryProvider extends ClassFileTreeNodeFactoryProvider { + protected static final ImageIcon MODULE_FILE_ICON = new ImageIcon(ClassFileTreeNodeFactoryProvider.class.getClassLoader().getResource("org/jd/gui/images/module_obj.png")); protected static final Factory FACTORY = new Factory(); static { @@ -41,7 +45,33 @@ public class ModuleInfoFileTreeNodeFactoryProvider extends ClassFileTreeNodeFact public 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); + return (T)new ModuleInfoFileTreeNode(entry, new TreeNodeBean(label, CLASS_FILE_ICON), FACTORY); + } + + protected static class ModuleInfoFileTreeNode extends FileTreeNode { + public ModuleInfoFileTreeNode(Container.Entry entry, Object userObject, PageAndTipFactory pageAndTipFactory) { + super(entry, null, userObject, pageAndTipFactory); + } + + // --- TreeNodeExpandable --- // + @Override + public void populateTreeNode(API api) { + if (!initialized) { + removeAllChildren(); + // Create type node + TypeFactory typeFactory = api.getTypeFactory(entry); + + if (typeFactory != null) { + Collection types = typeFactory.make(api, entry); + + for (Type type : types) { + add(new BaseTreeNode(entry, type.getName(), new TreeNodeBean(type.getDisplayTypeName(), MODULE_FILE_ICON), factory)); + } + } + + initialized = true; + } + } } protected static class Factory implements AbstractTypeFileTreeNodeFactoryProvider.PageAndTipFactory { diff --git a/services/src/main/java/org/jd/gui/util/decompiler/StringBuilderPrinter.java b/services/src/main/java/org/jd/gui/util/decompiler/StringBuilderPrinter.java index d97d474f..4d98095e 100644 --- a/services/src/main/java/org/jd/gui/util/decompiler/StringBuilderPrinter.java +++ b/services/src/main/java/org/jd/gui/util/decompiler/StringBuilderPrinter.java @@ -10,89 +10,89 @@ import org.jd.core.v1.api.printer.Printer; public class StringBuilderPrinter implements Printer { - protected static final String TAB = " "; - protected static final String NEWLINE = "\n"; - - protected StringBuilder stringBuffer = new StringBuilder(10*1024); - - protected boolean unicodeEscape = true; - protected boolean realignmentLineNumber = false; - - protected int majorVersion = 0; - protected int minorVersion = 0; - protected int indentationCount; - - public void setUnicodeEscape(boolean unicodeEscape) { this.unicodeEscape = unicodeEscape; } - public void setRealignmentLineNumber(boolean realignmentLineNumber) { this.realignmentLineNumber = realignmentLineNumber; } - - public int getMajorVersion() { return majorVersion; } - public int getMinorVersion() { return minorVersion; } - public StringBuilder getStringBuffer() { return stringBuffer; } - - public void append(char c) { stringBuffer.append(c); } - public void append(String s) { stringBuffer.append(s); } - - protected void printEscape(String s) { - if (unicodeEscape && (s != null)) { - int length = s.length(); - - for (int i=0; i> 3))); - append((char) ('0' + (c & 0x7))); - } else if (c > 127) { - // Write octal format - append("\\u"); - - int z = (c >> 12); - append((char) ((z <= 9) ? ('0' + z) : (('A' - 10) + z))); - z = ((c >> 8) & 0xF); - append((char) ((z <= 9) ? ('0' + z) : (('A' - 10) + z))); - z = ((c >> 4) & 0xF); - append((char) ((z <= 9) ? ('0' + z) : (('A' - 10) + z))); - z = (c & 0xF); - append((char) ((z <= 9) ? ('0' + z) : (('A' - 10) + z))); - } else { - append(c); - } - } - } else { - append(s); - } - } - - // --- Printer --- // - @Override - public void start(int maxLineNumber, int majorVersion, int minorVersion) { - this.stringBuffer.setLength(0); - this.majorVersion = majorVersion; - this.minorVersion = minorVersion; - this.indentationCount = 0; - } - - @Override public void end() {} - - @Override public void printText(String text) { printEscape(text); } - @Override public void printNumericConstant(String constant) { append(constant); } - @Override public void printStringConstant(String constant, String ownerInternalName) { append(constant); } - @Override public void printKeyword(String keyword) { append(keyword); } - - @Override public void printDeclaration(int flags, String internalTypeName, String name, String descriptor) { append(name); } - @Override public void printReference(int flags, String internalTypeName, String name, String descriptor, String ownerInternalName) { append(name); } - - @Override public void indent() { indentationCount++; } - @Override public void unindent() { if (indentationCount > 0) indentationCount--; } - - @Override public void startLine(int lineNumber) { for (int i=0; i 0) append(NEWLINE); } - - @Override public void startMarker(int type) {} - @Override public void endMarker(int type) {} + protected static final String TAB = " "; + protected static final String NEWLINE = "\n"; + + protected StringBuilder stringBuffer = new StringBuilder(10*1024); + + protected boolean unicodeEscape = true; + protected boolean realignmentLineNumber = false; + + protected int majorVersion = 0; + protected int minorVersion = 0; + protected int indentationCount; + + public void setUnicodeEscape(boolean unicodeEscape) { this.unicodeEscape = unicodeEscape; } + public void setRealignmentLineNumber(boolean realignmentLineNumber) { this.realignmentLineNumber = realignmentLineNumber; } + + public int getMajorVersion() { return majorVersion; } + public int getMinorVersion() { return minorVersion; } + public StringBuilder getStringBuffer() { return stringBuffer; } + + public void append(char c) { stringBuffer.append(c); } + public void append(String s) { stringBuffer.append(s); } + + protected void printEscape(String s) { + if (unicodeEscape && (s != null)) { + int length = s.length(); + + for (int i=0; i> 3))); + append((char) ('0' + (c & 0x7))); + } else if (c > 127) { + // Write octal format + append("\\u"); + + int z = (c >> 12); + append((char) ((z <= 9) ? ('0' + z) : (('A' - 10) + z))); + z = ((c >> 8) & 0xF); + append((char) ((z <= 9) ? ('0' + z) : (('A' - 10) + z))); + z = ((c >> 4) & 0xF); + append((char) ((z <= 9) ? ('0' + z) : (('A' - 10) + z))); + z = (c & 0xF); + append((char) ((z <= 9) ? ('0' + z) : (('A' - 10) + z))); + } else { + append(c); + } + } + } else { + append(s); + } + } + + // --- Printer --- // + @Override + public void start(int maxLineNumber, int majorVersion, int minorVersion) { + this.stringBuffer.setLength(0); + this.majorVersion = majorVersion; + this.minorVersion = minorVersion; + this.indentationCount = 0; + } + + @Override public void end() {} + + @Override public void printText(String text) { printEscape(text); } + @Override public void printNumericConstant(String constant) { append(constant); } + @Override public void printStringConstant(String constant, String ownerInternalName) { append(constant); } + @Override public void printKeyword(String keyword) { append(keyword); } + + @Override public void printDeclaration(int type, String internalTypeName, String name, String descriptor) { append(name); } + @Override public void printReference(int type, String internalTypeName, String name, String descriptor, String ownerInternalName) { append(name); } + + @Override public void indent() { indentationCount++; } + @Override public void unindent() { if (indentationCount > 0) indentationCount--; } + + @Override public void startLine(int lineNumber) { for (int i=0; i 0) append(NEWLINE); } + + @Override public void startMarker(int type) {} + @Override public void endMarker(int type) {} } diff --git a/services/src/main/java/org/jd/gui/util/index/IndexesUtil.java b/services/src/main/java/org/jd/gui/util/index/IndexesUtil.java index 48af6ea4..68972972 100644 --- a/services/src/main/java/org/jd/gui/util/index/IndexesUtil.java +++ b/services/src/main/java/org/jd/gui/util/index/IndexesUtil.java @@ -19,11 +19,20 @@ public class IndexesUtil { public static boolean containsInternalTypeName(Collection> collectionOfFutureIndexes, String internalTypeName) { + return contains(collectionOfFutureIndexes, "typeDeclarations", internalTypeName); + } + + @SuppressWarnings("unchecked") + public static List findInternalTypeName(Collection> collectionOfFutureIndexes, String internalTypeName) { + return find(collectionOfFutureIndexes, "typeDeclarations", internalTypeName); + } + + public static boolean contains(Collection> collectionOfFutureIndexes, String indexName, String key) { try { for (Future futureIndexes : collectionOfFutureIndexes) { if (futureIndexes.isDone()) { - Map index = futureIndexes.get().getIndex("typeDeclarations"); - if ((index != null) && (index.get(internalTypeName) != null)) { + Map index = futureIndexes.get().getIndex(indexName); + if ((index != null) && (index.get(key) != null)) { return true; } } @@ -36,15 +45,15 @@ public static boolean containsInternalTypeName(Collection> colle } @SuppressWarnings("unchecked") - public static List findInternalTypeName(Collection> collectionOfFutureIndexes, String internalTypeName) { + public static List find(Collection> collectionOfFutureIndexes, String indexName, String key) { ArrayList entries = new ArrayList<>(); try { for (Future futureIndexes : collectionOfFutureIndexes) { if (futureIndexes.isDone()) { - Map index = futureIndexes.get().getIndex("typeDeclarations"); + Map index = futureIndexes.get().getIndex(indexName); if (index != null) { - Collection collection = index.get(internalTypeName); + Collection collection = index.get(key); if (collection != null) { entries.addAll(collection); } diff --git a/services/src/main/java/org/jd/gui/view/component/ClassFilePage.java b/services/src/main/java/org/jd/gui/view/component/ClassFilePage.java index 67cf1ed1..a3a5a0a0 100644 --- a/services/src/main/java/org/jd/gui/view/component/ClassFilePage.java +++ b/services/src/main/java/org/jd/gui/view/component/ClassFilePage.java @@ -169,45 +169,45 @@ public void printStringConstant(String constant, String ownerInternalName) { } @Override - public void printDeclaration(int flags, String internalTypeName, String name, String descriptor) { + public void printDeclaration(int type, String internalTypeName, String name, String descriptor) { if (internalTypeName == null) internalTypeName = "null"; if (name == null) name = "null"; if (descriptor == null) descriptor = "null"; - switch (flags) { - case TYPE_FLAG: + switch (type) { + case TYPE: TypePage.DeclarationData data = new TypePage.DeclarationData(stringBuffer.length(), name.length(), internalTypeName, null, null); declarations.put(internalTypeName, data); typeDeclarations.put(stringBuffer.length(), data); break; - case CONSTRUCTOR_FLAG: + case CONSTRUCTOR: declarations.put(internalTypeName + "--" + descriptor, new TypePage.DeclarationData(stringBuffer.length(), name.length(), internalTypeName, "", descriptor)); break; default: declarations.put(internalTypeName + '-' + name + '-' + descriptor, new TypePage.DeclarationData(stringBuffer.length(), name.length(), internalTypeName, name, descriptor)); break; } - super.printDeclaration(flags, internalTypeName, name, descriptor); + super.printDeclaration(type, internalTypeName, name, descriptor); } @Override - public void printReference(int flags, String internalTypeName, String name, String descriptor, String ownerInternalName) { + public void printReference(int type, String internalTypeName, String name, String descriptor, String ownerInternalName) { if (internalTypeName == null) internalTypeName = "null"; if (name == null) name = "null"; if (descriptor == null) descriptor = "null"; - switch (flags) { - case TYPE_FLAG: + switch (type) { + case TYPE: addHyperlink(new TypePage.HyperlinkReferenceData(stringBuffer.length(), name.length(), newReferenceData(internalTypeName, null, null, ownerInternalName))); break; - case CONSTRUCTOR_FLAG: + case CONSTRUCTOR: addHyperlink(new TypePage.HyperlinkReferenceData(stringBuffer.length(), name.length(), newReferenceData(internalTypeName, "", descriptor, ownerInternalName))); break; default: addHyperlink(new TypePage.HyperlinkReferenceData(stringBuffer.length(), name.length(), newReferenceData(internalTypeName, name, descriptor, ownerInternalName))); break; } - super.printReference(flags, internalTypeName, name, descriptor, ownerInternalName); + super.printReference(type, internalTypeName, name, descriptor, ownerInternalName); } @Override diff --git a/services/src/main/java/org/jd/gui/view/component/ModuleInfoFilePage.java b/services/src/main/java/org/jd/gui/view/component/ModuleInfoFilePage.java index 8222ab4a..29609c9e 100644 --- a/services/src/main/java/org/jd/gui/view/component/ModuleInfoFilePage.java +++ b/services/src/main/java/org/jd/gui/view/component/ModuleInfoFilePage.java @@ -8,13 +8,28 @@ package org.jd.gui.view.component; import org.fife.ui.rsyntaxtextarea.*; +import org.fife.ui.rtextarea.Marker; import org.jd.gui.api.API; import org.jd.gui.api.model.Container; +import org.jd.gui.api.model.Indexes; import org.jd.gui.util.decompiler.ContainerLoader; +import org.jd.gui.util.decompiler.StringBuilderPrinter; import org.jd.gui.util.exception.ExceptionUtil; +import org.jd.gui.util.index.IndexesUtil; import javax.swing.text.Segment; -import java.util.Map; +import java.awt.*; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.*; +import java.util.List; +import java.util.concurrent.Future; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static org.jd.core.v1.api.printer.Printer.MODULE; +import static org.jd.core.v1.api.printer.Printer.PACKAGE; +import static org.jd.core.v1.api.printer.Printer.TYPE; public class ModuleInfoFilePage extends ClassFilePage { public static final String SYNTAX_STYLE_JAVA_MODULE = "text/java-module"; @@ -29,6 +44,7 @@ public ModuleInfoFilePage(API api, Container.Entry entry) { super(api, entry); } + @Override public void decompile(Map preferences) { try { // Clear ... @@ -59,9 +75,199 @@ public void decompile(Map preferences) { } } + @Override public String getSyntaxStyle() { return SYNTAX_STYLE_JAVA_MODULE; } - public class ModuleInfoFilePrinter extends ClassFilePrinter { + @Override + protected void openHyperlink(int x, int y, HyperlinkData hyperlinkData) { + HyperlinkReferenceData hyperlinkReferenceData = (HyperlinkReferenceData)hyperlinkData; + + if (hyperlinkReferenceData.reference.enabled) { + try { + // Save current position in history + Point location = textArea.getLocationOnScreen(); + int offset = textArea.viewToModel(new Point(x - location.x, y - location.y)); + URI uri = entry.getUri(); + api.addURI(new URI(uri.getScheme(), uri.getAuthority(), uri.getPath(), "position=" + offset, null)); + + // Open link + ModuleInfoReferenceData moduleInfoReferenceData = (ModuleInfoReferenceData)hyperlinkReferenceData.reference; + List entries; + String fragment; + + switch (moduleInfoReferenceData.type) { + case TYPE: + entries = IndexesUtil.findInternalTypeName(collectionOfFutureIndexes, fragment = moduleInfoReferenceData.typeName); + break; + case PACKAGE: + entries = IndexesUtil.find(collectionOfFutureIndexes, "packageDeclarations", moduleInfoReferenceData.typeName); + fragment = null; + break; + default: // MODULE + entries = IndexesUtil.find(collectionOfFutureIndexes, "javaModuleDeclarations", moduleInfoReferenceData.name); + fragment = moduleInfoReferenceData.typeName; + break; + } + + if (entries.contains(entry)) { + api.openURI(uri); + } else { + String rootUri = entry.getContainer().getRoot().getUri().toString(); + ArrayList sameContainerEntries = new ArrayList<>(); + + for (Container.Entry entry : entries) { + if (entry.getUri().toString().startsWith(rootUri)) { + sameContainerEntries.add(entry); + } + } + + if (sameContainerEntries.size() > 0) { + api.openURI(x, y, sameContainerEntries, null, fragment); + } else if (entries.size() > 0) { + api.openURI(x, y, entries, null, fragment); + } + } + } catch (URISyntaxException e) { + assert ExceptionUtil.printStackTrace(e); + } + } + } + + // --- UriOpenable --- // + @Override + public boolean openUri(URI uri) { + ArrayList ranges = new ArrayList<>(); + String fragment = uri.getFragment(); + String query = uri.getQuery(); + + Marker.clearMarkAllHighlights(textArea); + + if ((fragment != null) && (declarations.size() == 1)) { + DeclarationData declaration = declarations.entrySet().iterator().next().getValue(); + + if (fragment.equals(declaration.typeName)) { + ranges.add(new DocumentRange(declaration.startPosition, declaration.endPosition)); + } + } + + if (query != null) { + Map parameters = parseQuery(query); + + String highlightFlags = parameters.get("highlightFlags"); + String highlightPattern = parameters.get("highlightPattern"); + + if ((highlightFlags != null) && (highlightPattern != null)) { + String regexp = createRegExp(highlightPattern); + Pattern pattern = Pattern.compile(regexp + ".*"); + + boolean t = (highlightFlags.indexOf('t') != -1); // Highlight types + boolean M = (highlightFlags.indexOf('M') != -1); // Highlight modules + + if (highlightFlags.indexOf('d') != -1) { + // Highlight declarations + for (Map.Entry entry : declarations.entrySet()) { + DeclarationData declaration = entry.getValue(); + + if (M) { + matchAndAddDocumentRange(pattern, declaration.name, declaration.startPosition, declaration.endPosition, ranges); + } + } + } + + if (highlightFlags.indexOf('r') != -1) { + // Highlight references + for (Map.Entry entry : hyperlinks.entrySet()) { + HyperlinkData hyperlink = entry.getValue(); + ReferenceData reference = ((HyperlinkReferenceData)hyperlink).reference; + ModuleInfoReferenceData moduleInfoReferenceData = (ModuleInfoReferenceData)reference; + + if (t && (moduleInfoReferenceData.type == TYPE)) { + matchAndAddDocumentRange(pattern, getMostInnerTypeName(moduleInfoReferenceData.typeName), hyperlink.startPosition, hyperlink.endPosition, ranges); + } + if (M && (moduleInfoReferenceData.type == MODULE)) { + matchAndAddDocumentRange(pattern, moduleInfoReferenceData.name, hyperlink.startPosition, hyperlink.endPosition, ranges); + } + } + } + } + } + + if ((ranges != null) && !ranges.isEmpty()) { + textArea.setMarkAllHighlightColor(SELECT_HIGHLIGHT_COLOR); + Marker.markAll(textArea, ranges); + ranges.sort(null); + setCaretPositionAndCenter(ranges.get(0)); + } + + return true; + } + + // --- IndexesChangeListener --- // + @Override + public void indexesChanged(Collection> collectionOfFutureIndexes) { + // Update the list of containers + this.collectionOfFutureIndexes = collectionOfFutureIndexes; + // Refresh links + boolean refresh = false; + + for (ReferenceData reference : references) { + ModuleInfoReferenceData moduleInfoReferenceData = (ModuleInfoReferenceData)reference; + boolean enabled = false; + + try { + for (Future futureIndexes : collectionOfFutureIndexes) { + if (futureIndexes.isDone()) { + Map index; + String key; + + switch (moduleInfoReferenceData.type) { + case TYPE: + index = futureIndexes.get().getIndex("typeDeclarations"); + key = reference.typeName; + break; + case PACKAGE: + index = futureIndexes.get().getIndex("packageDeclarations"); + key = reference.typeName; + break; + default: // MODULE + index = futureIndexes.get().getIndex("javaModuleDeclarations"); + key = reference.name; + break; + } + + if ((index != null) && (index.get(key) != null)) { + enabled = true; + break; + } + } + } + } catch (Exception e) { + assert ExceptionUtil.printStackTrace(e); + } + + if (reference.enabled != enabled) { + reference.enabled = enabled; + refresh = true; + } + } + + if (refresh) { + textArea.repaint(); + } + } + + protected static class ModuleInfoReferenceData extends ReferenceData { + public int type; + + public ModuleInfoReferenceData(int type, String typeName, String name, String descriptor, String owner) { + super(typeName, name, descriptor, owner); + this.type = type; + } + } + + public class ModuleInfoFilePrinter extends StringBuilderPrinter { + protected HashMap referencesCache = new HashMap<>(); + @Override public void start(int maxLineNumber, int majorVersion, int minorVersion) {} @@ -70,6 +276,27 @@ public void end() { setText(stringBuffer.toString()); initLineNumbers(); } + + @Override + public void printDeclaration(int type, String internalTypeName, String name, String descriptor) { + declarations.put(internalTypeName, new TypePage.DeclarationData(stringBuffer.length(), name.length(), internalTypeName, name, descriptor)); + super.printDeclaration(type, internalTypeName, name, descriptor); + } + + @Override + public void printReference(int type, String internalTypeName, String name, String descriptor, String ownerInternalName) { + String key = (type == MODULE) ? name : internalTypeName; + ReferenceData reference = referencesCache.get(key); + + if (reference == null) { + reference = new ModuleInfoReferenceData(type, internalTypeName, name, descriptor, ownerInternalName); + referencesCache.put(key, reference); + references.add(reference); + } + + addHyperlink(new HyperlinkReferenceData(stringBuffer.length(), name.length(), reference)); + super.printReference(type, internalTypeName, name, descriptor, ownerInternalName); + } } // https://github.com/bobbylight/RSyntaxTextArea/wiki/Adding-Syntax-Highlighting-for-a-new-Language diff --git a/services/src/main/java/org/jd/gui/view/component/TypePage.java b/services/src/main/java/org/jd/gui/view/component/TypePage.java index b407953d..99dcaa9b 100644 --- a/services/src/main/java/org/jd/gui/view/component/TypePage.java +++ b/services/src/main/java/org/jd/gui/view/component/TypePage.java @@ -343,23 +343,7 @@ public void indexesChanged(Collection> collectionOfFutureIndexes String typeName = reference.typeName; boolean enabled; - if (reference.name != null) { - try { - // Recursive search - typeName = searchTypeHavingMember(typeName, reference.name, reference.descriptor, entry); - if (typeName != null) { - // Replace type with the real type having the referenced member - reference.typeName = typeName; - enabled = true; - } else { - enabled = false; - } - } catch (Error e) { - // Catch StackOverflowError or OutOfMemoryError - assert ExceptionUtil.printStackTrace(e); - enabled = false; - } - } else { + if (reference.name == null) { enabled = false; try { @@ -375,6 +359,22 @@ public void indexesChanged(Collection> collectionOfFutureIndexes } catch (Exception e) { assert ExceptionUtil.printStackTrace(e); } + } else { + try { + // Recursive search + typeName = searchTypeHavingMember(typeName, reference.name, reference.descriptor, entry); + if (typeName != null) { + // Replace type with the real type having the referenced member + reference.typeName = typeName; + enabled = true; + } else { + enabled = false; + } + } catch (Error e) { + // Catch StackOverflowError or OutOfMemoryError + assert ExceptionUtil.printStackTrace(e); + enabled = false; + } } if (reference.enabled != enabled) { @@ -505,7 +505,7 @@ public HyperlinkReferenceData(int startPosition, int length, ReferenceData refer } } - public static class ReferenceData { + protected static class ReferenceData { public String typeName; /** * Field or method name or null for type @@ -525,7 +525,7 @@ public static class ReferenceData { */ public boolean enabled = false; - ReferenceData(String typeName, String name, String descriptor, String owner) { + public ReferenceData(String typeName, String name, String descriptor, String owner) { this.typeName = typeName; this.name = name; this.descriptor = descriptor; diff --git a/services/src/main/resources/META-INF/services/org.jd.gui.spi.ContainerFactory b/services/src/main/resources/META-INF/services/org.jd.gui.spi.ContainerFactory index f8a5ecc5..31f9fea7 100644 --- a/services/src/main/resources/META-INF/services/org.jd.gui.spi.ContainerFactory +++ b/services/src/main/resources/META-INF/services/org.jd.gui.spi.ContainerFactory @@ -1,5 +1,5 @@ # Order is important : 'GenericContainerFactoryProvider' must be the last -org.jd.gui.service.container.JmodContainerFactoryProvider +org.jd.gui.service.container.JavaModuleContainerFactoryProvider org.jd.gui.service.container.EarContainerFactoryProvider org.jd.gui.service.container.WarContainerFactoryProvider org.jd.gui.service.container.JarContainerFactoryProvider diff --git a/services/src/main/resources/META-INF/services/org.jd.gui.spi.FileLoader b/services/src/main/resources/META-INF/services/org.jd.gui.spi.FileLoader index 28758244..65b9dbe6 100644 --- a/services/src/main/resources/META-INF/services/org.jd.gui.spi.FileLoader +++ b/services/src/main/resources/META-INF/services/org.jd.gui.spi.FileLoader @@ -3,7 +3,7 @@ org.jd.gui.service.fileloader.ClassFileLoaderProvider org.jd.gui.service.fileloader.EarFileLoaderProvider org.jd.gui.service.fileloader.JarFileLoaderProvider org.jd.gui.service.fileloader.JavaFileLoaderProvider -org.jd.gui.service.fileloader.JmodFileLoaderProvider +org.jd.gui.service.fileloader.JavaModuleFileLoaderProvider org.jd.gui.service.fileloader.LogFileLoaderProvider org.jd.gui.service.fileloader.WarFileLoaderProvider org.jd.gui.service.fileloader.ZipFileLoaderProvider diff --git a/services/src/main/resources/META-INF/services/org.jd.gui.spi.Indexer b/services/src/main/resources/META-INF/services/org.jd.gui.spi.Indexer index 1e23c160..73259c47 100644 --- a/services/src/main/resources/META-INF/services/org.jd.gui.spi.Indexer +++ b/services/src/main/resources/META-INF/services/org.jd.gui.spi.Indexer @@ -2,6 +2,8 @@ org.jd.gui.service.indexer.DirectoryIndexerProvider org.jd.gui.service.indexer.ClassFileIndexerProvider org.jd.gui.service.indexer.EjbJarXmlFileIndexerProvider org.jd.gui.service.indexer.JavaFileIndexerProvider +org.jd.gui.service.indexer.JavaModuleFileIndexerProvider +org.jd.gui.service.indexer.JavaModuleInfoFileIndexerProvider org.jd.gui.service.indexer.MetainfServiceFileIndexerProvider org.jd.gui.service.indexer.TextFileIndexerProvider org.jd.gui.service.indexer.WebXmlFileIndexerProvider diff --git a/services/src/main/resources/META-INF/services/org.jd.gui.spi.TreeNodeFactory b/services/src/main/resources/META-INF/services/org.jd.gui.spi.TreeNodeFactory index d9f2f9bd..697007d1 100644 --- a/services/src/main/resources/META-INF/services/org.jd.gui.spi.TreeNodeFactory +++ b/services/src/main/resources/META-INF/services/org.jd.gui.spi.TreeNodeFactory @@ -10,8 +10,8 @@ org.jd.gui.service.treenode.HtmlFileTreeNodeFactoryProvider org.jd.gui.service.treenode.JarFileTreeNodeFactoryProvider org.jd.gui.service.treenode.JavaFileTreeNodeFactoryProvider org.jd.gui.service.treenode.JavascriptFileTreeNodeFactoryProvider -org.jd.gui.service.treenode.JmodFileTreeNodeFactoryProvider -org.jd.gui.service.treenode.JmodPackageTreeNodeFactoryProvider +org.jd.gui.service.treenode.JavaModuleFileTreeNodeFactoryProvider +org.jd.gui.service.treenode.JavaModulePackageTreeNodeFactoryProvider org.jd.gui.service.treenode.JsonFileTreeNodeFactoryProvider org.jd.gui.service.treenode.JspFileTreeNodeFactoryProvider org.jd.gui.service.treenode.ManifestFileTreeNodeFactoryProvider diff --git a/services/src/main/resources/org/jd/gui/images/module_obj.png b/services/src/main/resources/org/jd/gui/images/module_obj.png new file mode 100644 index 00000000..300adac0 Binary files /dev/null and b/services/src/main/resources/org/jd/gui/images/module_obj.png differ diff --git a/services/src/main/resources/org/jd/gui/images/packd_obj.png b/services/src/main/resources/org/jd/gui/images/packd_obj.png new file mode 100644 index 00000000..aa7b6a66 Binary files /dev/null and b/services/src/main/resources/org/jd/gui/images/packd_obj.png differ diff --git a/services/src/main/resources/org/jd/gui/images/th_showqualified.png b/services/src/main/resources/org/jd/gui/images/th_showqualified.png new file mode 100644 index 00000000..702c3298 Binary files /dev/null and b/services/src/main/resources/org/jd/gui/images/th_showqualified.png differ