f4d78b6850c3971e1a8ca81cf020e8ba98073cd2
[idea/community.git] / java / java-psi-impl / src / com / intellij / psi / impl / compiled / ClassFileStubBuilder.java
1 // Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 package com.intellij.psi.impl.compiled;
3
4 import com.intellij.openapi.diagnostic.Logger;
5 import com.intellij.openapi.vfs.VirtualFile;
6 import com.intellij.psi.compiled.ClassFileDecompilers;
7 import com.intellij.psi.impl.source.JavaFileElementType;
8 import com.intellij.psi.stubs.BinaryFileStubBuilder;
9 import com.intellij.psi.stubs.PsiFileStub;
10 import com.intellij.psi.stubs.Stub;
11 import com.intellij.util.cls.ClsFormatException;
12 import com.intellij.util.indexing.FileContent;
13 import org.jetbrains.annotations.NotNull;
14 import org.jetbrains.annotations.Nullable;
15
16 import java.util.stream.Stream;
17
18 import static com.intellij.psi.compiled.ClassFileDecompilers.Full;
19
20 public class ClassFileStubBuilder implements BinaryFileStubBuilder.CompositeBinaryFileStubBuilder<ClassFileDecompilers.Decompiler> {
21   private static final Logger LOG = Logger.getInstance(ClassFileStubBuilder.class);
22
23   public static final int STUB_VERSION = 25 + JavaFileElementType.STUB_VERSION;
24
25   @Override
26   public boolean acceptsFile(@NotNull VirtualFile file) {
27     return true;
28   }
29
30   @Override
31   public @NotNull Stream<ClassFileDecompilers.Decompiler> getAllSubBuilders() {
32     return ClassFileDecompilers.getInstance().EP_NAME.extensions().filter(decompiler -> decompiler instanceof Full);
33   }
34
35   @Override
36   public @Nullable ClassFileDecompilers.Decompiler getSubBuilder(@NotNull FileContent fileContent) {
37     return fileContent.getFile()
38       .computeWithPreloadedContentHint(fileContent.getContent(), () -> ClassFileDecompilers.getInstance().find(fileContent.getFile()));
39   }
40
41   @Override
42   public @NotNull String getSubBuilderVersion(@Nullable ClassFileDecompilers.Decompiler decompiler) {
43     if (decompiler == null) return "default";
44     int version = decompiler instanceof Full ? ((Full)decompiler).getStubBuilder().getStubVersion() : 0;
45     return decompiler.getClass().getName() + ":" + version;
46   }
47
48   @Override
49   public @Nullable Stub buildStubTree(@NotNull FileContent fileContent, @Nullable ClassFileDecompilers.Decompiler decompiler) {
50     return fileContent.getFile().computeWithPreloadedContentHint(fileContent.getContent(), () -> {
51       VirtualFile file = fileContent.getFile();
52       try {
53         if (decompiler instanceof Full) {
54           return ((Full)decompiler).getStubBuilder().buildFileStub(fileContent);
55         }
56       }
57       catch (ClsFormatException e) {
58         if (LOG.isDebugEnabled()) LOG.debug(file.getPath(), e);
59         else LOG.info(file.getPath() + ": " + e.getMessage());
60       }
61
62       try {
63         PsiFileStub<?> stub = ClsFileImpl.buildFileStub(file, fileContent.getContent());
64         if (stub == null && fileContent.getFileName().indexOf('$') < 0) {
65           LOG.info("No stub built for the file " + fileContent);
66         }
67         return stub;
68       }
69       catch (ClsFormatException e) {
70         if (LOG.isDebugEnabled()) LOG.debug(file.getPath(), e);
71         else LOG.info(file.getPath() + ": " + e.getMessage());
72       }
73
74       return null;
75     });
76   }
77
78   @Override
79   public int getStubVersion() {
80     return STUB_VERSION;
81   }
82 }