use of meghanada.reflect.MemberDescriptor in project meghanada-server by mopemope.
the class ASMReflector method reflectAll.
private List<MemberDescriptor> reflectAll(final File file, final String targetClass, final List<String> targetClasses) throws IOException {
if (ModuleHelper.isJrtFsFile(file)) {
final List<MemberDescriptor> results = new ArrayList<>(64);
ModuleHelper.walkModule(path -> {
ModuleHelper.pathToClassData(path).ifPresent(cd -> {
String className = cd.getClassName();
String moduleName = cd.getModuleName();
if (this.ignorePackage(className)) {
return;
}
final Iterator<String> classIterator = targetClasses.iterator();
while (classIterator.hasNext()) {
final String nameWithTP = classIterator.next();
if (nonNull(nameWithTP)) {
final boolean isSuper = !targetClass.equals(nameWithTP);
final String nameWithoutTP = ClassNameUtils.removeTypeParameter(nameWithTP);
if (className.equals(nameWithoutTP)) {
try (final InputStream in = cd.getInputStream()) {
final ClassReader classReader = new ClassReader(in);
final List<MemberDescriptor> members = getMemberFromJar(file, classReader, nameWithoutTP, nameWithTP);
if (isSuper) {
replaceDescriptorsType(nameWithTP, members);
}
results.addAll(members);
classIterator.remove();
break;
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
final String innerClassName = ClassNameUtils.replaceInnerMark(className);
if (innerClassName.equals(nameWithoutTP)) {
try (final InputStream in = cd.getInputStream()) {
final ClassReader classReader = new ClassReader(in);
final List<MemberDescriptor> members = this.getMemberFromJar(file, classReader, innerClassName, nameWithTP);
if (isSuper) {
replaceDescriptorsType(nameWithTP, members);
}
results.addAll(members);
classIterator.remove();
break;
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
}
}
});
});
return results;
} else if (file.isFile() && file.getName().endsWith(".jar")) {
try (final JarFile jarFile = new JarFile(file)) {
final Enumeration<JarEntry> entries = jarFile.entries();
final List<MemberDescriptor> results = new ArrayList<>(64);
while (entries.hasMoreElements()) {
if (targetClasses.isEmpty()) {
break;
}
final JarEntry jarEntry = entries.nextElement();
final String entryName = jarEntry.getName();
if (!entryName.endsWith(".class")) {
continue;
}
final String className = ClassNameUtils.replaceSlash(entryName.substring(0, entryName.length() - 6));
if (this.ignorePackage(className)) {
continue;
}
final Iterator<String> classIterator = targetClasses.iterator();
while (classIterator.hasNext()) {
final String nameWithTP = classIterator.next();
if (nonNull(nameWithTP)) {
final boolean isSuper = !targetClass.equals(nameWithTP);
final String nameWithoutTP = ClassNameUtils.removeTypeParameter(nameWithTP);
if (className.equals(nameWithoutTP)) {
try (final InputStream in = jarFile.getInputStream(jarEntry)) {
final ClassReader classReader = new ClassReader(in);
final List<MemberDescriptor> members = this.getMemberFromJar(file, classReader, nameWithoutTP, nameWithTP);
if (isSuper) {
replaceDescriptorsType(nameWithTP, members);
}
results.addAll(members);
classIterator.remove();
break;
}
}
final String innerClassName = ClassNameUtils.replaceInnerMark(className);
if (innerClassName.equals(nameWithoutTP)) {
try (final InputStream in = jarFile.getInputStream(jarEntry)) {
final ClassReader classReader = new ClassReader(in);
final List<MemberDescriptor> members = this.getMemberFromJar(file, classReader, innerClassName, nameWithTP);
if (isSuper) {
replaceDescriptorsType(nameWithTP, members);
}
results.addAll(members);
classIterator.remove();
break;
}
}
}
}
}
return results;
}
} else if (file.isFile() && file.getName().endsWith(".class")) {
for (String nameWithTP : targetClasses) {
final boolean isSuper = !targetClass.equals(nameWithTP);
final String fqcn = ClassNameUtils.removeTypeParameter(nameWithTP);
final List<MemberDescriptor> members = getMembersFromClassFile(file, file, fqcn, false);
if (nonNull(members)) {
// 1 file
if (isSuper) {
replaceDescriptorsType(nameWithTP, members);
}
return members;
}
}
return Collections.emptyList();
} else if (file.isDirectory()) {
try (final Stream<Path> pathStream = Files.walk(file.toPath());
final Stream<File> stream = pathStream.map(Path::toFile).filter(f -> f.isFile() && f.getName().endsWith(".class")).collect(Collectors.toList()).stream()) {
return stream.map(wrapIO(f -> {
final String rootPath = file.getCanonicalPath();
final String path = f.getCanonicalPath();
final String className = ClassNameUtils.replaceSlash(path.substring(rootPath.length() + 1, path.length() - 6));
final Iterator<String> stringIterator = targetClasses.iterator();
while (stringIterator.hasNext()) {
final String nameWithTP = stringIterator.next();
final boolean isSuper = !targetClass.equals(nameWithTP);
final String fqcn = ClassNameUtils.removeTypeParameter(nameWithTP);
if (!className.equals(fqcn)) {
continue;
}
final List<MemberDescriptor> members = getMembersFromClassFile(file, f, fqcn, false);
if (nonNull(members)) {
if (isSuper) {
replaceDescriptorsType(nameWithTP, members);
}
// found
stringIterator.remove();
return members;
}
}
return Collections.<MemberDescriptor>emptyList();
})).filter(memberDescriptors -> nonNull(memberDescriptors) && memberDescriptors.size() > 0).flatMap(Collection::stream).collect(Collectors.toList());
}
}
return Collections.emptyList();
}
use of meghanada.reflect.MemberDescriptor in project meghanada-server by mopemope.
the class CachedASMReflector method replaceTypeParameters.
private static List<MemberDescriptor> replaceTypeParameters(String className, String classWithTP, List<MemberDescriptor> members) {
int idx = classWithTP.indexOf('<');
if (idx >= 0) {
List<String> types = ClassNameUtils.parseTypeParameter(classWithTP);
List<String> realTypes = ClassNameUtils.parseTypeParameter(className);
for (MemberDescriptor md : members) {
if (md.hasTypeParameters()) {
md.clearTypeParameterMap();
int realSize = realTypes.size();
for (int i = 0; i < types.size(); i++) {
String t = types.get(i);
if (realSize > i) {
String real = realTypes.get(i);
md.putTypeParameter(t, real);
}
}
}
String declaringClass = ClassNameUtils.removeTypeParameter(md.getDeclaringClass());
if (className.startsWith(declaringClass)) {
md.setDeclaringClass(className);
}
}
}
return members;
}
use of meghanada.reflect.MemberDescriptor in project meghanada-server by mopemope.
the class CachedASMReflector method reflect.
public List<MemberDescriptor> reflect(final String className) {
final ClassName cn = new ClassName(className);
// check type parameter
final String classWithoutTP = cn.getName();
final GlobalCache globalCache = GlobalCache.getInstance();
try {
final List<MemberDescriptor> members = new ArrayList<>(16);
List<MemberDescriptor> list = globalCache.getMemberDescriptors(classWithoutTP);
for (final MemberDescriptor md : list) {
members.add(md.clone());
}
if (cn.hasTypeParameter()) {
return this.replaceMembers(classWithoutTP, className, members);
}
return members;
} catch (ExecutionException e) {
throw new UncheckedExecutionException(e);
}
}
use of meghanada.reflect.MemberDescriptor in project meghanada-server by mopemope.
the class ReferenceSearcher method searchMethodCallCondition.
private static Optional<SearchCondition> searchMethodCallCondition(Source source, int line, int col, String symbol) {
EntryMessage msg = log.traceEntry("line={} col={} symbol={}", line, col, symbol);
Optional<MethodCall> mcResult = source.getMethodCall(line, col, true);
Optional<SearchCondition> result = mcResult.map(mc -> {
String methodName = mc.name;
List<String> arguments = mc.getArguments();
String declaringClass = mc.declaringClass;
if (isNull(declaringClass)) {
return null;
}
MemberDescriptor method = searchMatchMethod(declaringClass, methodName, arguments).orElseGet(() -> searchMatchConstructor(declaringClass, arguments).orElse(null));
if (isNull(method)) {
// not match
return null;
}
MethodDescriptor md = (MethodDescriptor) method;
if (md.getMemberType().equals(CandidateUnit.MemberType.CONSTRUCTOR)) {
return new SearchCondition(mc.declaringClass, mc.name, SearchCondition.Type.CONSTRUCTOR, mc.getArguments());
}
return new SearchCondition(mc.declaringClass, mc.name, SearchCondition.Type.METHOD, mc.getArguments());
});
log.traceExit(msg);
return result;
}
use of meghanada.reflect.MemberDescriptor in project meghanada-server by mopemope.
the class MemberCacheLoader method load.
@Override
public List<MemberDescriptor> load(final String className) throws IOException {
final ClassName cn = new ClassName(className);
final String fqcn = cn.getName();
final String projectRoot = Config.getProjectRoot();
File classFile = MemberCacheLoader.getClassFile(fqcn);
if (isNull(classFile)) {
// try inner class
classFile = MemberCacheLoader.getClassFile(ClassNameUtils.replaceInnerMark(fqcn));
if (isNull(classFile)) {
log.debug("Missing FQCN:{}'s file is null", fqcn);
return Collections.emptyList();
}
}
String classFilePath = classFile.getPath();
boolean isMyProject = classFilePath.startsWith(projectRoot);
if (!isMyProject) {
final Stopwatch stopwatch = Stopwatch.createStarted();
final List<MemberDescriptor> members = loadFromReflector(fqcn);
log.trace("load fqcn:{} elapsed:{}", fqcn, stopwatch.stop());
if (!members.isEmpty()) {
storeMembers(fqcn, members);
return members;
}
}
@SuppressWarnings("unchecked") final List<MemberDescriptor> cachedResult = MemberCacheLoader.getCachedMemberDescriptors(fqcn);
if (nonNull(cachedResult)) {
return cachedResult;
}
final Stopwatch stopwatch = Stopwatch.createStarted();
final List<MemberDescriptor> members = loadFromReflector(fqcn);
log.trace("load fqcn:{} elapsed:{}", fqcn, stopwatch.stop());
storeMembers(fqcn, members);
return members;
}
Aggregations