|
|
|
/*
|
|
|
|
* Copyright 2000-2015 JetBrains s.r.o.
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
package org.jetbrains.java.decompiler.main.collectors;
|
|
|
|
|
|
|
|
import org.jetbrains.java.decompiler.main.ClassesProcessor;
|
|
|
|
import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode;
|
|
|
|
import org.jetbrains.java.decompiler.main.DecompilerContext;
|
|
|
|
import org.jetbrains.java.decompiler.main.TextBuffer;
|
|
|
|
import org.jetbrains.java.decompiler.struct.StructContext;
|
|
|
|
|
|
|
|
import java.util.*;
|
|
|
|
import java.util.Map.Entry;
|
|
|
|
|
|
|
|
|
|
|
|
public class ImportCollector {
|
|
|
|
|
|
|
|
private static final String JAVA_LANG_PACKAGE = "java.lang";
|
|
|
|
|
|
|
|
private final Map<String, String> mapSimpleNames = new HashMap<String, String>();
|
|
|
|
private final Set<String> setNotImportedNames = new HashSet<String>();
|
|
|
|
private String currentPackageSlash = "";
|
|
|
|
private String currentPackagePoint = "";
|
|
|
|
|
|
|
|
public ImportCollector(ClassNode root) {
|
|
|
|
|
|
|
|
String clname = root.classStruct.qualifiedName;
|
|
|
|
int index = clname.lastIndexOf("/");
|
|
|
|
if (index >= 0) {
|
|
|
|
currentPackageSlash = clname.substring(0, index);
|
|
|
|
currentPackagePoint = currentPackageSlash.replace('/', '.');
|
|
|
|
currentPackageSlash += "/";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public String getShortName(String fullname) {
|
|
|
|
return getShortName(fullname, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
public String getShortName(String fullname, boolean imported) {
|
|
|
|
|
|
|
|
ClassesProcessor clproc = DecompilerContext.getClassProcessor();
|
|
|
|
ClassNode node = clproc.getMapRootClasses().get(fullname.replace('.', '/'));
|
|
|
|
|
|
|
|
String retname = null;
|
|
|
|
|
|
|
|
if (node != null && node.classStruct.isOwn()) {
|
|
|
|
|
|
|
|
retname = node.simpleName;
|
|
|
|
|
|
|
|
while (node.parent != null && node.type == ClassNode.CLASS_MEMBER) {
|
|
|
|
retname = node.parent.simpleName + "." + retname;
|
|
|
|
node = node.parent;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (node.type == ClassNode.CLASS_ROOT) {
|
|
|
|
fullname = node.classStruct.qualifiedName;
|
|
|
|
fullname = fullname.replace('/', '.');
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return retname;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
fullname = fullname.replace('$', '.');
|
|
|
|
}
|
|
|
|
|
|
|
|
String nshort = fullname;
|
|
|
|
String npackage = "";
|
|
|
|
|
|
|
|
int lastpoint = fullname.lastIndexOf(".");
|
|
|
|
|
|
|
|
if (lastpoint >= 0) {
|
|
|
|
nshort = fullname.substring(lastpoint + 1);
|
|
|
|
npackage = fullname.substring(0, lastpoint);
|
|
|
|
}
|
|
|
|
|
|
|
|
StructContext context = DecompilerContext.getStructContext();
|
|
|
|
|
|
|
|
// check for another class which could 'shadow' this one. Two cases:
|
|
|
|
// 1) class with the same short name in the current package
|
|
|
|
// 2) class with the same short name in the default package
|
|
|
|
boolean existsDefaultClass = (context.getClass(currentPackageSlash + nshort) != null
|
|
|
|
&& !npackage.equals(currentPackagePoint)) // current package
|
|
|
|
|| (context.getClass(nshort) != null
|
|
|
|
&& !currentPackagePoint.isEmpty()); // default package
|
|
|
|
|
|
|
|
if (existsDefaultClass ||
|
|
|
|
(mapSimpleNames.containsKey(nshort) && !npackage.equals(mapSimpleNames.get(nshort)))) {
|
|
|
|
return fullname;
|
|
|
|
}
|
|
|
|
else if (!mapSimpleNames.containsKey(nshort)) {
|
|
|
|
mapSimpleNames.put(nshort, npackage);
|
|
|
|
|
|
|
|
if (!imported) {
|
|
|
|
setNotImportedNames.add(nshort);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return retname == null ? nshort : retname;
|
|
|
|
}
|
|
|
|
|
|
|
|
public int writeImports(TextBuffer buffer) {
|
|
|
|
int importlines_written = 0;
|
|
|
|
|
|
|
|
List<String> imports = packImports();
|
|
|
|
|
|
|
|
for (String s : imports) {
|
|
|
|
buffer.append("import ");
|
|
|
|
buffer.append(s);
|
|
|
|
buffer.append(";");
|
|
|
|
buffer.appendLineSeparator();
|
|
|
|
|
|
|
|
importlines_written++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return importlines_written;
|
|
|
|
}
|
|
|
|
|
|
|
|
private List<String> packImports() {
|
|
|
|
List<Entry<String, String>> lst = new ArrayList<Entry<String, String>>(mapSimpleNames.entrySet());
|
|
|
|
|
|
|
|
Collections.sort(lst, new Comparator<Entry<String, String>>() {
|
|
|
|
public int compare(Entry<String, String> par0, Entry<String, String> par1) {
|
|
|
|
int res = par0.getValue().compareTo(par1.getValue());
|
|
|
|
if (res == 0) {
|
|
|
|
res = par0.getKey().compareTo(par1.getKey());
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
List<String> res = new ArrayList<String>();
|
|
|
|
for (Entry<String, String> ent : lst) {
|
|
|
|
// exclude a current class or one of the nested ones, java.lang and empty packages
|
|
|
|
if (!setNotImportedNames.contains(ent.getKey()) &&
|
|
|
|
!JAVA_LANG_PACKAGE.equals(ent.getValue()) &&
|
|
|
|
!ent.getValue().isEmpty()) {
|
|
|
|
res.add(ent.getValue() + "." + ent.getKey());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
}
|