use of meghanada.reflect.ClassIndex in project meghanada-server by mopemope.
the class ClassSignatureVisitorTest method testComplexType1.
@org.junit.Test
public void testComplexType1() throws Exception {
String fqcn = "com.google.common.util.concurrent.AbstractCheckedFuture";
File jar = getJar("guava");
ClassSignatureVisitor visitor = doAnalyze(jar, fqcn);
assertEquals("com.google.common.util.concurrent.AbstractCheckedFuture", visitor.getName());
List<String> expected = new ArrayList<>();
expected.add("V");
expected.add("X");
assertEquals(expected, visitor.getTypeParameters());
visitor.getSuperClasses().forEach(cd -> System.out.println("super:" + cd.getClassName()));
final ClassIndex index = visitor.getClassIndex();
assertEquals(false, index.isInterface());
assertEquals(2, index.getSupers().size());
}
use of meghanada.reflect.ClassIndex in project meghanada-server by mopemope.
the class TreeAnalyzer method markFQCN.
private static String markFQCN(Source src, String fqcn, boolean markUnUse) {
if (fqcn.equals("void")) {
return fqcn;
}
if (fqcn.startsWith("capture of") || fqcn.equals("any") || fqcn.equals("<any>")) {
// log.warn("unknown type={}", fqcn);
return fqcn;
}
String simpleName = ClassNameUtils.removeTypeAndArray(fqcn);
simpleName = ClassNameUtils.removeWildcard(simpleName);
if (ClassNameUtils.isPrimitive(simpleName)) {
return fqcn;
}
// checkLoadable(src, fqcn, simpleName);
for (String s : ClassNameUtils.parseTypeParameter(fqcn)) {
if (s.startsWith(ClassNameUtils.CAPTURE_OF)) {
String cls = ClassNameUtils.removeCapture(s);
if (cls.equals(ClassNameUtils.CAPTURE_OF)) {
String ignore = markFQCN(src, ClassNameUtils.OBJECT_CLASS);
} else {
String ignore = markFQCN(src, cls);
}
} else {
String ignore = markFQCN(src, s);
}
}
CachedASMReflector cachedASMReflector = CachedASMReflector.getInstance();
Map<String, ClassIndex> classIndex = cachedASMReflector.getGlobalClassIndex();
if (!src.importClasses.contains(simpleName) && !classIndex.containsKey(simpleName)) {
src.addUnknown(simpleName);
} else {
if (markUnUse) {
// contains
String name = ClassNameUtils.replaceInnerMark(simpleName);
if (src.unused.contains(name)) {
src.unused.remove(name);
}
int i = simpleName.indexOf('$');
if (i > 0) {
String parentClass = simpleName.substring(0, i);
if (src.unused.contains(parentClass)) {
src.unused.remove(parentClass);
}
}
}
File classFile = cachedASMReflector.getClassFile(simpleName);
if (isNull(classFile) || !classFile.getName().endsWith(".jar")) {
src.usingClasses.add(simpleName);
}
}
return fqcn;
}
use of meghanada.reflect.ClassIndex in project meghanada-server by mopemope.
the class DeclarationSearcher method searchClassOrInterface.
private static Optional<Declaration> searchClassOrInterface(final Source source, final Integer line, final Integer col, final String symbol) {
// TODO need tune
final EntryMessage entryMessage = log.traceEntry("line={} col={} symbol={}", line, col, symbol);
final CachedASMReflector reflector = CachedASMReflector.getInstance();
Optional<Declaration> result;
String fqcn = source.getImportedClassFQCN(symbol, null);
if (fqcn == null) {
if (!source.getPackageName().isEmpty()) {
fqcn = source.getPackageName() + '.' + symbol;
result = reflector.containsClassIndex(fqcn).map(classIndex -> {
final Declaration declaration = new Declaration(symbol, classIndex.getReturnType(), Declaration.Type.CLASS, 0);
return Optional.of(declaration);
}).orElseGet(() -> {
final Set<String> parents = new HashSet<>(8);
for (final ClassScope classScope : source.getClassScopes()) {
final String className = classScope.getFQCN();
parents.add(className);
}
parents.addAll(source.importClasses);
for (final ClassIndex ci : reflector.searchInnerClasses(parents)) {
final String returnType = ci.getReturnType();
if (returnType.endsWith(symbol)) {
final Declaration d = new Declaration(symbol, returnType, Declaration.Type.CLASS, 0);
return Optional.of(d);
}
}
return Optional.empty();
});
} else {
result = Optional.empty();
}
} else {
final Declaration declaration = new Declaration(symbol, fqcn, Declaration.Type.CLASS, 0);
result = Optional.of(declaration);
}
log.traceExit(entryMessage);
return result;
}
use of meghanada.reflect.ClassIndex in project meghanada-server by mopemope.
the class ASMReflector method readClassIndex.
private static void readClassIndex(final Map<ClassIndex, File> indexes, final InputStream in, final File file, boolean allowSuper) throws IOException {
final ClassReader classReader = new ClassReader(in);
final String className = ClassNameUtils.replaceSlash(classReader.getClassName());
final boolean projectOutput = file.isDirectory();
final int access = classReader.getAccess();
final boolean isPublic = (Opcodes.ACC_PUBLIC & access) == Opcodes.ACC_PUBLIC;
final boolean isProtected = (Opcodes.ACC_PROTECTED & access) == Opcodes.ACC_PROTECTED;
final boolean isInterface = (Opcodes.ACC_INTERFACE & access) == Opcodes.ACC_INTERFACE;
final boolean isAnnotation = (Opcodes.ACC_ANNOTATION & access) == Opcodes.ACC_ANNOTATION;
boolean isSuper = false;
if (allowSuper) {
isSuper = (Opcodes.ACC_SUPER & access) == Opcodes.ACC_SUPER;
}
if (projectOutput) {
final ClassAnalyzeVisitor classAnalyzeVisitor = new ClassAnalyzeVisitor(className, true, false);
classReader.accept(classAnalyzeVisitor, 0);
final ClassIndex classIndex = classAnalyzeVisitor.getClassIndex();
classIndex.setInterface(isInterface);
classIndex.setAnnotation(isAnnotation);
indexes.put(classIndex, file);
} else {
if (isPublic || isProtected || isSuper) {
final ClassAnalyzeVisitor classAnalyzeVisitor = new ClassAnalyzeVisitor(className, true, false);
classReader.accept(classAnalyzeVisitor, 0);
final ClassIndex classIndex = classAnalyzeVisitor.getClassIndex();
classIndex.setInterface(isInterface);
classIndex.setAnnotation(isAnnotation);
indexes.put(classIndex, file);
}
}
}
use of meghanada.reflect.ClassIndex in project meghanada-server by mopemope.
the class ASMReflector method getClassIndexes.
Map<String, ClassIndex> getClassIndexes(File file) throws IOException {
Map<ClassIndex, File> classes = this.getClasses(file);
Map<String, ClassIndex> result = new HashMap<>(classes.size());
classes.forEach((index, f) -> {
final String fqcn = index.getRawDeclaration();
try {
if (ModuleHelper.isJrtFsFile(f)) {
index.setFilePath(f.getPath());
} else {
index.setFilePath(f.getCanonicalPath());
}
} catch (IOException e) {
throw new UncheckedIOException(e);
}
result.put(fqcn, index);
});
return result;
}
Aggregations