Cleanup (test)
[idea/community.git] / plugins / java-decompiler / plugin / test / org / jetbrains / java / decompiler / IdeaDecompilerTest.java
1 /*
2  * Copyright 2000-2014 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package org.jetbrains.java.decompiler;
17
18 import com.intellij.codeInsight.daemon.impl.IdentifierHighlighterPassFactory;
19 import com.intellij.codeInsight.navigation.actions.GotoDeclarationAction;
20 import com.intellij.debugger.PositionManager;
21 import com.intellij.openapi.application.PluginPathManager;
22 import com.intellij.openapi.fileTypes.StdFileTypes;
23 import com.intellij.openapi.util.SystemInfo;
24 import com.intellij.openapi.util.registry.Registry;
25 import com.intellij.openapi.util.registry.RegistryValue;
26 import com.intellij.openapi.vfs.StandardFileSystems;
27 import com.intellij.openapi.vfs.VfsUtilCore;
28 import com.intellij.openapi.vfs.VirtualFile;
29 import com.intellij.openapi.vfs.VirtualFileVisitor;
30 import com.intellij.pom.Navigatable;
31 import com.intellij.psi.PsiElement;
32 import com.intellij.psi.PsiFile;
33 import com.intellij.psi.impl.compiled.ClsFileImpl;
34 import com.intellij.testFramework.PlatformTestUtil;
35 import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
36 import com.intellij.util.containers.ContainerUtil;
37 import org.jetbrains.annotations.NotNull;
38
39 import java.util.Set;
40
41 public class IdeaDecompilerTest extends LightCodeInsightFixtureTestCase {
42   @Override
43   protected void setUp() throws Exception {
44     super.setUp();
45     myFixture.setTestDataPath(PluginPathManager.getPluginHomePath("java-decompiler") + "/plugin/testData");
46   }
47
48   public void testSimple() {
49     String path = PlatformTestUtil.getRtJarPath() + "!/java/lang/String.class";
50     VirtualFile file = StandardFileSystems.jar().findFileByPath(path);
51     assertNotNull(path, file);
52
53     String decompiled = new IdeaDecompiler().getText(file).toString();
54     assertTrue(decompiled, decompiled.startsWith(IdeaDecompiler.BANNER + "package java.lang;\n"));
55     assertTrue(decompiled, decompiled.contains("public final class String"));
56     assertTrue(decompiled, decompiled.contains("@deprecated"));
57     assertTrue(decompiled, decompiled.contains("private static class CaseInsensitiveComparator"));
58     assertFalse(decompiled, decompiled.contains("{ /* compiled code */ }"));
59     assertFalse(decompiled, decompiled.contains("synthetic"));
60   }
61
62   public void testStubCompatibility() {
63     String path = PlatformTestUtil.getRtJarPath() + "!/java";
64     VirtualFile dir = StandardFileSystems.jar().findFileByPath(path);
65     assertNotNull(path, dir);
66     doTestStubCompatibility(dir);
67   }
68
69   private void doTestStubCompatibility(VirtualFile root) {
70     VfsUtilCore.visitChildrenRecursively(root, new VirtualFileVisitor() {
71       @Override
72       public boolean visitFile(@NotNull VirtualFile file) {
73         if (file.isDirectory()) {
74           System.out.println(file.getPath());
75         }
76         else if (file.getFileType() == StdFileTypes.CLASS && !file.getName().contains("$") && !skip(file)) {
77           PsiFile clsFile = getPsiManager().findFile(file);
78           assertNotNull(file.getPath(), clsFile);
79           PsiElement mirror = ((ClsFileImpl)clsFile).getMirror();
80           String decompiled = mirror.getText();
81           assertTrue(file.getPath(), decompiled.contains(file.getNameWithoutExtension()));
82         }
83         return true;
84       }
85
86       private boolean skip(VirtualFile file) {
87         if (!SystemInfo.isJavaVersionAtLeast("1.8")) return false;
88         String path = file.getPath();
89         int p = path.indexOf("!/");
90         return p > 0 && knowProblems.contains(path.substring(p + 2));
91       }
92
93       // todo[r.sh] drop when IDEA-129734 get fixed
94       private final Set<String> knowProblems = ContainerUtil.newHashSet(
95         "java/lang/reflect/AnnotatedElement.class", "java/util/stream/Nodes.class", "java/util/stream/FindOps.class",
96         "java/util/stream/Collectors.class", "java/util/stream/DistinctOps.class", "java/util/stream/IntPipeline.class",
97         "java/util/stream/LongPipeline.class", "java/util/stream/DoublePipeline.class"
98       );
99     });
100   }
101
102   public void testNavigation() {
103     myFixture.openFileInEditor(getTestFile("Navigation.class"));
104     doTestNavigation(11, 14, 14, 10);  // to "m2()"
105     doTestNavigation(15, 21, 14, 17);  // to "int i"
106     doTestNavigation(16, 28, 15, 13);  // to "int r"
107   }
108
109   public void testHighlighting() {
110     myFixture.openFileInEditor(getTestFile("Navigation.class"));
111     IdentifierHighlighterPassFactory.doWithHighlightingEnabled(new Runnable() {
112       public void run() {
113         myFixture.getEditor().getCaretModel().moveToOffset(offset(11, 14));  // m2(): usage, declaration
114         assertEquals(2, myFixture.doHighlighting().size());
115         myFixture.getEditor().getCaretModel().moveToOffset(offset(15, 21));  // int i: usage, declaration
116         assertEquals(2, myFixture.doHighlighting().size());
117         myFixture.getEditor().getCaretModel().moveToOffset(offset(16, 28));  // int r: usage, declaration
118         assertEquals(2, myFixture.doHighlighting().size());
119         myFixture.getEditor().getCaretModel().moveToOffset(offset(19, 24));  // throws: declaration, m4() call
120         assertEquals(2, myFixture.doHighlighting().size());
121       }
122     });
123   }
124
125   private VirtualFile getTestFile(String name) {
126     String path = myFixture.getTestDataPath() + "/" + name;
127     VirtualFile file = StandardFileSystems.local().refreshAndFindFileByPath(path);
128     assertNotNull(path, file);
129     return file;
130   }
131
132   private void doTestNavigation(int line, int column, int expectedLine, int expectedColumn) {
133     PsiElement target = GotoDeclarationAction.findTargetElement(getProject(), myFixture.getEditor(), offset(line, column));
134     assertTrue(String.valueOf(target), target instanceof Navigatable);
135     ((Navigatable)target).navigate(true);
136     int expected = offset(expectedLine, expectedColumn);
137     assertEquals(expected, myFixture.getCaretOffset());
138   }
139
140   private int offset(int line, int column) {
141     return myFixture.getEditor().getDocument().getLineStartOffset(line - 1) + column - 1;
142   }
143
144   public void testLineNumberMapping() {
145     RegistryValue value = Registry.get("decompiler.use.line.mapping");
146     boolean old = value.asBoolean();
147     try {
148       value.setValue(true);
149
150       VirtualFile file = getTestFile("LineNumbers.class");
151       assertNull(file.getUserData(PositionManager.LINE_NUMBERS_MAPPING_KEY));
152
153       new IdeaDecompiler().getText(file);
154
155       int[] mapping = file.getUserData(PositionManager.LINE_NUMBERS_MAPPING_KEY);
156       assertNotNull(mapping);
157       assertEquals(20, mapping.length);
158     }
159     finally {
160       value.setValue(old);
161     }
162   }
163 }