New decompiler API (ability to call default decompiler from extensions)

This commit is contained in:
Roman Shevchenko
2014-02-11 10:52:45 +01:00
parent c823858dd5
commit a582b91c0c
4 changed files with 97 additions and 34 deletions
@@ -13,36 +13,23 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* @author max
*/
package com.intellij.psi.impl.compiled;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.fileTypes.BinaryFileDecompiler;
import com.intellij.openapi.fileTypes.ContentBasedFileSubstitutor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiManager;
import com.intellij.psi.compiled.ClassFileDecompilers;
import org.jetbrains.annotations.NotNull;
public class ClassFileDecompiler implements BinaryFileDecompiler {
/** @deprecated temporary solution, to remove in IDEA 14 */
@SuppressWarnings("deprecation")
public class DeprecatedClassFileDecompiler implements ClassFileDecompiler.PlatformDecompiler {
@Override
@NotNull
public CharSequence decompile(@NotNull VirtualFile file) {
ClassFileDecompilers.Decompiler decompiler = ClassFileDecompilers.find(file);
if (decompiler instanceof ClassFileDecompilers.Full) {
PsiManager manager = PsiManager.getInstance(ProjectManager.getInstance().getDefaultProject());
return ((ClassFileDecompilers.Full)decompiler).createFileViewProvider(file, manager, true).getContents();
}
Project[] projects = ProjectManager.getInstance().getOpenProjects();
if (projects.length > 0) {
Project project = projects[0];
//noinspection deprecation
for (ContentBasedFileSubstitutor processor : Extensions.getExtensions(ContentBasedFileSubstitutor.EP_NAME)) {
if (processor.isApplicable(project, file)) {
return processor.obtainFileText(project, file);
@@ -50,6 +37,6 @@ public class ClassFileDecompiler implements BinaryFileDecompiler {
}
}
return ClsFileImpl.decompile(file);
return null;
}
}
@@ -0,0 +1,64 @@
/*
* Copyright 2000-2014 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 com.intellij.psi.impl.compiled;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.fileTypes.BinaryFileDecompiler;
import com.intellij.openapi.project.DefaultProjectFactory;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiManager;
import com.intellij.psi.compiled.ClassFileDecompilers;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author max
*/
public class ClassFileDecompiler implements BinaryFileDecompiler {
/** @deprecated temporary solution, to remove in IDEA 14 */
public interface PlatformDecompiler {
@Nullable
CharSequence decompile(@NotNull VirtualFile file);
}
@Override
@NotNull
public CharSequence decompile(@NotNull VirtualFile file) {
ClassFileDecompilers.Decompiler decompiler = ClassFileDecompilers.find(file);
if (decompiler instanceof ClassFileDecompilers.Full) {
PsiManager manager = PsiManager.getInstance(DefaultProjectFactory.getInstance().getDefaultProject());
return ((ClassFileDecompilers.Full)decompiler).createFileViewProvider(file, manager, true).getContents();
}
@SuppressWarnings("deprecation") PlatformDecompiler platformDecompiler = ServiceManager.getService(PlatformDecompiler.class);
if (platformDecompiler != null) {
CharSequence result = platformDecompiler.decompile(file);
if (result != null) return result;
}
return decompileText(file);
}
@NotNull
public static CharSequence decompileText(@NotNull VirtualFile file) {
ClassFileDecompilers.Decompiler decompiler = ClassFileDecompilers.find(file);
if (decompiler instanceof ClassFileDecompilers.Light) {
return ((ClassFileDecompilers.Light)decompiler).getText(file);
}
return ClsFileImpl.decompile(file);
}
}
@@ -35,7 +35,6 @@ import com.intellij.openapi.util.ModificationTracker;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.compiled.ClassFileDecompilers;
import com.intellij.psi.impl.JavaPsiImplementationHelper;
import com.intellij.psi.impl.PsiFileEx;
import com.intellij.psi.impl.java.stubs.PsiClassStub;
@@ -73,6 +72,8 @@ public class ClsFileImpl extends ClsRepositoryPsiElement<PsiClassHolderFileStub>
implements PsiJavaFile, PsiFileWithStubSupport, PsiFileEx, Queryable, PsiClassOwnerEx, PsiCompiledFile {
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.compiled.ClsFileImpl");
private static final ThreadLocal<PsiClassHolderFileStub<?>> ourStubToProcess = new ThreadLocal<PsiClassHolderFileStub<?>>();
/** NOTE: you absolutely MUST NOT hold PsiLock under the mirror lock */
private final Object myMirrorLock = new Object();
private final Object myStubLock = new Object();
@@ -317,7 +318,7 @@ public class ClsFileImpl extends ClsRepositoryPsiElement<PsiClassHolderFileStub>
mirrorTreeElement = myMirrorFileElement;
if (mirrorTreeElement == null) {
VirtualFile file = getVirtualFile();
CharSequence mirrorText = decompile(file, getStub());
CharSequence mirrorText = decompileInternal(file);
String ext = JavaFileType.INSTANCE.getDefaultExtension();
PsiClass[] classes = getClasses();
@@ -496,30 +497,36 @@ public class ClsFileImpl extends ClsRepositoryPsiElement<PsiClassHolderFileStub>
// default decompiler implementation
@NotNull
public static CharSequence decompile(@NotNull VirtualFile file) {
ClassFileDecompilers.Decompiler decompiler = ClassFileDecompilers.find(file);
if (decompiler instanceof ClassFileDecompilers.Light) {
return ((ClassFileDecompilers.Light)decompiler).getText(file);
}
PsiJavaFileStub stub = null;
private CharSequence decompileInternal(VirtualFile file) {
ourStubToProcess.set(getStub());
try {
stub = buildFileStub(file, file.contentsToByteArray());
return ClassFileDecompiler.decompileText(file);
}
catch (Exception e) {
LOG.warn(e);
finally {
ourStubToProcess.set(null);
}
return stub == null ? "" : decompile(file, stub);
}
@NotNull
private static CharSequence decompile(@NotNull VirtualFile file, @NotNull PsiClassHolderFileStub<?> stub) {
PsiManager manager = PsiManager.getInstance(DefaultProjectFactory.getInstance().getDefaultProject());
public static CharSequence decompile(@NotNull VirtualFile file) {
PsiClassHolderFileStub<?> stub = ourStubToProcess.get();
if (stub == null) {
try {
stub = buildFileStub(file, file.contentsToByteArray());
}
catch (Exception e) {
LOG.warn(e);
}
}
if (stub == null) {
return "";
}
PsiManager manager = PsiManager.getInstance(DefaultProjectFactory.getInstance().getDefaultProject());
ClsFileImpl psi = new ClsFileImpl(new ClassFileViewProvider(manager, file), stub);
if (stub.getPsi() == null) {
((PsiJavaFileStubImpl)stub).setPsi(psi);
@SuppressWarnings("unchecked") PsiFileStubImpl<PsiFile> impl = (PsiFileStubImpl)stub;
impl.setPsi(psi);
}
StringBuilder buffer = new StringBuilder();
+5
View File
@@ -231,7 +231,9 @@
<extensionPoint name="psi.classFileDecompiler" interface="com.intellij.psi.compiled.ClassFileDecompilers$Decompiler"/>
<!-- deprecated API -->
<!--suppress DeprecatedClassUsageInspection -->
<extensionPoint name="psi.clsCustomNavigationPolicy" interface="com.intellij.psi.impl.compiled.ClsCustomNavigationPolicy"/>
<!--suppress DeprecatedClassUsageInspection -->
<extensionPoint name="psi.clsDecompiledFileProvider" interface="com.intellij.psi.ClsFileDecompiledPsiFileProvider"/>
<extensionPoint name="vetoSPICondition" interface="com.intellij.openapi.util.Condition"/>
@@ -1017,6 +1019,9 @@
<filetype.decompiler filetype="CLASS" implementationClass="com.intellij.psi.impl.compiled.ClassFileDecompiler"/>
<filetype.stubBuilder filetype="CLASS" implementationClass="com.intellij.psi.impl.compiled.ClassFileStubBuilder"/>
<!--suppress DeprecatedClassUsageInspection -->
<applicationService serviceInterface="com.intellij.psi.impl.compiled.ClassFileDecompiler$PlatformDecompiler"
serviceImplementation="com.intellij.psi.impl.compiled.DeprecatedClassFileDecompiler"/>
<weigher key="proximity" implementationClass="com.intellij.psi.util.proximity.ReferenceListWeigher" id="referenceList"
order="before samePsiMember"/>