Search in sources :

Example 21 with MemberDescriptor

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();
}
Also used : Path(java.nio.file.Path) Enumeration(java.util.Enumeration) HashMap(java.util.HashMap) JarFile(java.util.jar.JarFile) FunctionUtils.wrapIOConsumer(meghanada.utils.FunctionUtils.wrapIOConsumer) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) JarEntry(java.util.jar.JarEntry) Map(java.util.Map) CandidateUnit(meghanada.reflect.CandidateUnit) Objects.isNull(java.util.Objects.isNull) Path(java.nio.file.Path) FunctionUtils.wrapIO(meghanada.utils.FunctionUtils.wrapIO) Opcodes(org.objectweb.asm.Opcodes) Iterator(java.util.Iterator) Files(java.nio.file.Files) ClassIndex(meghanada.reflect.ClassIndex) Collection(java.util.Collection) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) Set(java.util.Set) IOException(java.io.IOException) FileInputStream(java.io.FileInputStream) Collectors(java.util.stream.Collectors) File(java.io.File) UncheckedIOException(java.io.UncheckedIOException) MemberDescriptor(meghanada.reflect.MemberDescriptor) List(java.util.List) Stream(java.util.stream.Stream) Logger(org.apache.logging.log4j.Logger) ClassReader(org.objectweb.asm.ClassReader) ClassNameUtils(meghanada.utils.ClassNameUtils) ModuleHelper(meghanada.module.ModuleHelper) Optional(java.util.Optional) Objects.nonNull(java.util.Objects.nonNull) Collections(java.util.Collections) Config(meghanada.config.Config) LogManager(org.apache.logging.log4j.LogManager) InputStream(java.io.InputStream) Enumeration(java.util.Enumeration) MemberDescriptor(meghanada.reflect.MemberDescriptor) FileInputStream(java.io.FileInputStream) InputStream(java.io.InputStream) ArrayList(java.util.ArrayList) UncheckedIOException(java.io.UncheckedIOException) IOException(java.io.IOException) UncheckedIOException(java.io.UncheckedIOException) JarFile(java.util.jar.JarFile) JarEntry(java.util.jar.JarEntry) Iterator(java.util.Iterator) ClassReader(org.objectweb.asm.ClassReader) Collection(java.util.Collection) ArrayList(java.util.ArrayList) List(java.util.List) FileInputStream(java.io.FileInputStream) Stream(java.util.stream.Stream) InputStream(java.io.InputStream)

Example 22 with MemberDescriptor

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;
}
Also used : MemberDescriptor(meghanada.reflect.MemberDescriptor)

Example 23 with MemberDescriptor

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);
    }
}
Also used : GlobalCache(meghanada.cache.GlobalCache) UncheckedExecutionException(com.google.common.util.concurrent.UncheckedExecutionException) MemberDescriptor(meghanada.reflect.MemberDescriptor) ClassName(meghanada.utils.ClassName) ArrayList(java.util.ArrayList) UncheckedExecutionException(com.google.common.util.concurrent.UncheckedExecutionException) ExecutionException(java.util.concurrent.ExecutionException)

Example 24 with MemberDescriptor

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;
}
Also used : MemberDescriptor(meghanada.reflect.MemberDescriptor) EntryMessage(org.apache.logging.log4j.message.EntryMessage) MethodCall(meghanada.analyze.MethodCall) MethodDescriptor(meghanada.reflect.MethodDescriptor)

Example 25 with MemberDescriptor

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;
}
Also used : MemberDescriptor(meghanada.reflect.MemberDescriptor) ClassName(meghanada.utils.ClassName) Stopwatch(com.google.common.base.Stopwatch) File(java.io.File)

Aggregations

MemberDescriptor (meghanada.reflect.MemberDescriptor)26 File (java.io.File)17 Map (java.util.Map)17 ClassIndex (meghanada.reflect.ClassIndex)16 Stopwatch (com.google.common.base.Stopwatch)15 List (java.util.List)15 Config (meghanada.config.Config)15 MethodDescriptor (meghanada.reflect.MethodDescriptor)13 Test (org.junit.Test)13 GradleTestBase (meghanada.GradleTestBase)12 Config.debugIt (meghanada.config.Config.debugIt)12 Config.timeIt (meghanada.config.Config.timeIt)12 AfterClass (org.junit.AfterClass)12 Assert.assertEquals (org.junit.Assert.assertEquals)12 Assert.assertNotNull (org.junit.Assert.assertNotNull)12 BeforeClass (org.junit.BeforeClass)12 CandidateUnit (meghanada.reflect.CandidateUnit)6 CachedASMReflector (meghanada.reflect.asm.CachedASMReflector)5 IOException (java.io.IOException)4 ArrayList (java.util.ArrayList)4