From ff8433736fa7f3c0d3ac662a6e100a815dc4f79b Mon Sep 17 00:00:00 2001 From: Ilya Klyuchnikov Date: Wed, 11 Jun 2014 00:28:32 +0400 Subject: [PATCH] initial implementation for compound keys --- .../BytecodeAnalysisConverter.java | 249 +++++++++++++++++- .../codeInspection/bytecodeAnalysis/Data.java | 55 +++- .../BytecodeAnalysisTest.java | 85 +++++- .../bytecodeAnalysis/ExpectNoPsiKey.java | 26 ++ .../bytecodeAnalysis/data/Test02.java | 54 ++++ .../bytecodeAnalysis/data/Test03.java | 54 ++++ .../bytecodeAnalysis/data/TestAnnotation.java | 26 ++ 7 files changed, 532 insertions(+), 17 deletions(-) create mode 100644 java/java-tests/testSrc/com/intellij/codeInspection/bytecodeAnalysis/ExpectNoPsiKey.java create mode 100644 java/java-tests/testSrc/com/intellij/codeInspection/bytecodeAnalysis/data/Test02.java create mode 100644 java/java-tests/testSrc/com/intellij/codeInspection/bytecodeAnalysis/data/Test03.java create mode 100644 java/java-tests/testSrc/com/intellij/codeInspection/bytecodeAnalysis/data/TestAnnotation.java diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/BytecodeAnalysisConverter.java b/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/BytecodeAnalysisConverter.java index bc99541630ad..e980cc4aeb8d 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/BytecodeAnalysisConverter.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/BytecodeAnalysisConverter.java @@ -19,16 +19,26 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.PathManager; import com.intellij.openapi.components.ApplicationComponent; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.psi.*; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.util.TypeConversionUtil; import com.intellij.util.containers.HashMap; import com.intellij.util.containers.MostlySingularMultiMap; +import com.intellij.util.io.DataInputOutputUtil; +import com.intellij.util.io.KeyDescriptor; +import com.intellij.util.io.PersistentEnumeratorDelegate; import com.intellij.util.io.PersistentStringEnumerator; import gnu.trove.TIntObjectHashMap; import gnu.trove.TIntObjectIterator; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.org.objectweb.asm.Type; +import java.io.DataInput; +import java.io.DataOutput; import java.io.File; import java.io.IOException; +import java.util.Arrays; import java.util.Map; import java.util.Set; @@ -43,14 +53,23 @@ public class BytecodeAnalysisConverter implements ApplicationComponent { return ApplicationManager.getApplication().getComponent(BytecodeAnalysisConverter.class); } - PersistentStringEnumerator internalKeyEnumerator; + private PersistentStringEnumerator myInternalKeyEnumerator; + private PersistentStringEnumerator myPackageEnumerator; + private PersistentStringEnumerator myNamesEnumerator; + private PersistentEnumeratorDelegate myCompoundKeyEnumerator; @Override public void initComponent() { try { - File dir = new File(PathManager.getIndexRoot(), "bytecodeKeys"); - final File internalKeysFile = new File(dir, "faba.internalIds"); - internalKeyEnumerator = new PersistentStringEnumerator(internalKeysFile); + File keysDir = new File(PathManager.getIndexRoot(), "bytecodeKeys"); + final File internalKeysFile = new File(keysDir, "faba.internalIds"); + final File packageKeysFile = new File(keysDir, "faba.packages"); + final File namesFile = new File(keysDir, "faba.names1"); + final File compoundKeysFile = new File(keysDir, "faba.keys"); + myInternalKeyEnumerator = new PersistentStringEnumerator(internalKeysFile); + myPackageEnumerator = new PersistentStringEnumerator(packageKeysFile); + myNamesEnumerator = new PersistentStringEnumerator(namesFile); + myCompoundKeyEnumerator = new PersistentEnumeratorDelegate(compoundKeysFile, new IntArrayKeyDescriptor(), 1024 * 4); } catch (IOException e) { LOG.error(e); @@ -60,7 +79,10 @@ public class BytecodeAnalysisConverter implements ApplicationComponent { @Override public void disposeComponent() { try { - internalKeyEnumerator.close(); + myInternalKeyEnumerator.close(); + myPackageEnumerator.close(); + myNamesEnumerator.close(); + myCompoundKeyEnumerator.close(); } catch (IOException e) { LOG.error(e); @@ -88,7 +110,7 @@ public class BytecodeAnalysisConverter implements ApplicationComponent { int idI = 0; for (Key id : keyComponent) { // TODO refactor here - ids[idI] = internalKeyEnumerator.enumerate(internalKeyString(id)); + ids[idI] = myInternalKeyEnumerator.enumerate(internalKeyString(id)); idI++; } IntIdComponent intIdComponent = new IntIdComponent(ids); @@ -97,11 +119,11 @@ public class BytecodeAnalysisConverter implements ApplicationComponent { } result = new IntIdPending(pending.infinum, components); } - int key = internalKeyEnumerator.enumerate(internalKeyString(equation.id)); + int key = myInternalKeyEnumerator.enumerate(internalKeyString(equation.id)); return new IntIdEquation(key, result); } - static class InternalKey { + public static class InternalKey { final String annotationKey; final Direction dir; @@ -111,6 +133,182 @@ public class BytecodeAnalysisConverter implements ApplicationComponent { } } + @NotNull + public int[] mkCompoundKey(@NotNull Key key) throws IOException { + Direction direction = key.direction; + Method method = key.method; + + Type ownerType = Type.getType(method.internalClassName); + Type[] argTypes = Type.getArgumentTypes(method.methodDesc); + Type returnType = Type.getReturnType(method.methodDesc); + + int arity = argTypes.length; + int[] compoundKey = new int[9 + arity * 2]; + + compoundKey[0] = direction.directionId(); + compoundKey[1] = direction.paramId(); + compoundKey[2] = direction.valueId(); + writeType(compoundKey, 3, ownerType); + writeType(compoundKey, 5, returnType); + compoundKey[7] = myNamesEnumerator.enumerate(method.methodName); + compoundKey[8] = argTypes.length; + + for (int i = 0; i < argTypes.length; i++) { + writeType(compoundKey, 9 + 2*i, argTypes[i]); + } + return compoundKey; + } + + private void writeType(int[] compoundKey, int i, Type type) throws IOException { + String className = type.getClassName(); + int dotIndex = className.lastIndexOf('.'); + + String packageName; + String simpleName; + if (dotIndex > 0) { + packageName = className.substring(0, dotIndex); + simpleName = className.substring(dotIndex + 1); + } else { + packageName = ""; + simpleName = className; + } + + compoundKey[i] = myPackageEnumerator.enumerate(packageName); + compoundKey[i + 1] = myNamesEnumerator.enumerate(simpleName); + myPackageEnumerator.valueOf(compoundKey[i]); + myNamesEnumerator.valueOf(compoundKey[i + 1]); + } + + public String showCompoundKey(@NotNull int[] key) throws IOException { + StringBuilder sb = new StringBuilder(); + sb.append(key[0]); + sb.append(", "); + sb.append(key[1]); + sb.append(", "); + sb.append(key[2]); + sb.append(", "); + sb.append(myPackageEnumerator.valueOf(key[3])); + sb.append(", "); + sb.append(myNamesEnumerator.valueOf(key[4])); + sb.append(", "); + sb.append(myPackageEnumerator.valueOf(key[5])); + sb.append(", "); + sb.append(myNamesEnumerator.valueOf(key[6])); + sb.append(", "); + sb.append(myNamesEnumerator.valueOf(key[7])); + sb.append(", "); + sb.append(key[8]); + sb.append(", "); + + for (int i = 0; i < key[8]; i++) { + sb.append(myPackageEnumerator.valueOf(key[9 + 2*i])); + sb.append(", "); + sb.append(myNamesEnumerator.valueOf(key[9 + 2*i + 1])); + sb.append(", "); + + } + return sb.toString(); + } + + @Nullable + public int[] mkCompoundKey(@NotNull PsiMethod psiMethod, Direction direction) throws IOException { + + final PsiClass psiClass = PsiTreeUtil.getParentOfType(psiMethod, PsiClass.class, false); + if (psiClass == null) { + return null; + } + PsiClass outerClass = psiClass.getContainingClass(); + boolean isInnerClassConstructor = psiMethod.isConstructor() && (outerClass != null) && !psiClass.hasModifierProperty(PsiModifier.STATIC); + PsiParameter[] parameters = psiMethod.getParameterList().getParameters(); + + final int shift = isInnerClassConstructor ? 1 : 0; + final int arity = parameters.length + shift; + + int[] compoundKey = new int[9 + arity * 2]; + compoundKey[0] = direction.directionId(); + compoundKey[1] = direction.paramId(); + compoundKey[2] = direction.valueId(); + writeClass(compoundKey, 3, psiClass, 0); + + PsiType returnType = psiMethod.getReturnType(); + if (returnType == null) { + if (!writeType(compoundKey, 5, PsiType.VOID)) { + return null; + } + compoundKey[7] = myNamesEnumerator.enumerate(""); + } else { + if (!writeType(compoundKey, 5, returnType)) { + return null; + } + compoundKey[7] = myNamesEnumerator.enumerate(psiMethod.getName()); + } + compoundKey[8] = arity; + if (isInnerClassConstructor) { + writeClass(compoundKey, 9, outerClass, 0); + } + for (int i = 0; i < parameters.length; i++) { + PsiParameter parameter = parameters[i]; + if (!writeType(compoundKey, 9 + (2 * (i + shift)), parameter.getType())) { + return null; + } + } + + return compoundKey; + } + + private void writeClass(int[] compoundKey, int i, PsiClass psiClass, int dimensions) throws IOException { + String packageName = ""; + + PsiClassOwner psiFile = (PsiClassOwner) psiClass.getContainingFile(); + if (psiFile != null) { + packageName = psiFile.getPackageName(); + } + String qname = psiClass.getQualifiedName(); + String className = qname; + if (qname != null && packageName.length() > 0) { + className = qname.substring(packageName.length() + 1).replace('.', '$'); + } + compoundKey[i] = myPackageEnumerator.enumerate(packageName); + if (dimensions == 0) { + compoundKey[i + 1] = myNamesEnumerator.enumerate(className); + } else { + StringBuilder sb = new StringBuilder(className); + for (int j = 0; j < dimensions; j++) { + sb.append("[]"); + } + compoundKey[i + 1] = myNamesEnumerator.enumerate(sb.toString()); + } + } + + private boolean writeType(int[] compoundKey, int i, PsiType psiType) throws IOException { + int dimensions = 0; + psiType = TypeConversionUtil.erasure(psiType); + if (psiType instanceof PsiArrayType) { + PsiArrayType arrayType = (PsiArrayType)psiType; + psiType = arrayType.getDeepComponentType(); + dimensions = arrayType.getArrayDimensions(); + } + + if (psiType instanceof PsiClassType) { + PsiClass psiClass = ((PsiClassType)psiType).resolve(); + if (psiClass != null) { + writeClass(compoundKey, i, psiClass, dimensions); + return true; + } + else { + return false; + } + } + else if (psiType instanceof PsiPrimitiveType) { + String packageName = ""; + String className = psiType.getPresentableText(); + compoundKey[i] = myPackageEnumerator.enumerate(packageName); + compoundKey[i + 1] = myNamesEnumerator.enumerate(className); + return true; + } + return false; + } + public MostlySingularMultiMap makeAnnotations(TIntObjectHashMap internalIdSolutions) { MostlySingularMultiMap annotations = new MostlySingularMultiMap(); HashMap contracts = new HashMap(); @@ -124,7 +322,7 @@ public class BytecodeAnalysisConverter implements ApplicationComponent { } InternalKey key; try { - String s = internalKeyEnumerator.valueOf(inKey); + String s = myInternalKeyEnumerator.valueOf(inKey); key = readInternalKey(s); } catch (IOException e) { @@ -273,4 +471,37 @@ public class BytecodeAnalysisConverter implements ApplicationComponent { sb.append(')'); return sb.toString(); } + + private static class IntArrayKeyDescriptor implements KeyDescriptor { + + @Override + public void save(@NotNull DataOutput out, int[] value) throws IOException { + DataInputOutputUtil.writeINT(out, value.length); + for (int i : value) { + DataInputOutputUtil.writeINT(out, i); + } + } + + @Override + public int[] read(@NotNull DataInput in) throws IOException { + int[] value = new int[DataInputOutputUtil.readINT(in)]; + for (int i = 0; i < value.length; i++) { + value[i] = DataInputOutputUtil.readINT(in); + + } + return value; + } + + @Override + public int getHashCode(int[] value) { + return Arrays.hashCode(value); + } + + @Override + public boolean isEqual(int[] val1, int[] val2) { + return Arrays.equals(val1, val2); + } + } + + } diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/Data.java b/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/Data.java index 149dddb3bcd7..99a8feb2c52e 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/Data.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/Data.java @@ -52,7 +52,15 @@ enum Value { Bot, NotNull, Null, True, False, Top } -interface Direction {} +interface Direction { + static final int OUT_DIRECTION = 0; + static final int IN_DIRECTION = 1; + static final int INOUT_DIRECTION = 2; + int directionId(); + int paramId(); + int valueId(); +} + final class In implements Direction { final int paramIndex; @@ -78,6 +86,21 @@ final class In implements Direction { public int hashCode() { return paramIndex; } + + @Override + public int directionId() { + return IN_DIRECTION; + } + + @Override + public int paramId() { + return paramIndex; + } + + @Override + public int valueId() { + return 0; + } } final class InOut implements Direction { @@ -113,6 +136,21 @@ final class InOut implements Direction { public String toString() { return "InOut " + paramIndex + " " + inValue.toString(); } + + @Override + public int directionId() { + return INOUT_DIRECTION; + } + + @Override + public int paramId() { + return paramIndex; + } + + @Override + public int valueId() { + return inValue.ordinal(); + } } final class Out implements Direction { @@ -130,6 +168,21 @@ final class Out implements Direction { public boolean equals(Object obj) { return obj instanceof Out; } + + @Override + public int directionId() { + return OUT_DIRECTION; + } + + @Override + public int paramId() { + return 0; + } + + @Override + public int valueId() { + return 0; + } } final class Key { diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/bytecodeAnalysis/BytecodeAnalysisTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/bytecodeAnalysis/BytecodeAnalysisTest.java index a31eac7f7bf6..0825018f0682 100644 --- a/java/java-tests/testSrc/com/intellij/codeInspection/bytecodeAnalysis/BytecodeAnalysisTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInspection/bytecodeAnalysis/BytecodeAnalysisTest.java @@ -18,6 +18,9 @@ package com.intellij.codeInspection.bytecodeAnalysis; import com.intellij.codeInsight.AnnotationUtil; import com.intellij.codeInsight.InferredAnnotationsManager; import com.intellij.codeInspection.bytecodeAnalysis.data.Test01; +import com.intellij.codeInspection.bytecodeAnalysis.data.Test02; +import com.intellij.codeInspection.bytecodeAnalysis.data.Test03; +import com.intellij.codeInspection.bytecodeAnalysis.data.TestAnnotation; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; @@ -27,10 +30,14 @@ import com.intellij.testFramework.PsiTestUtil; import com.intellij.testFramework.fixtures.JavaCodeInsightFixtureTestCase; import com.intellij.util.ArrayUtil; import org.jetbrains.annotations.Contract; +import org.jetbrains.org.objectweb.asm.Type; +import org.junit.Assert; import java.io.File; import java.io.IOException; import java.lang.annotation.Annotation; +import java.lang.reflect.Constructor; +import java.util.Arrays; /** * @author lambdamix @@ -40,14 +47,25 @@ public class BytecodeAnalysisTest extends JavaCodeInsightFixtureTestCase { private final String myClassesProjectRelativePath = "/classes/" + Test01.class.getPackage().getName().replace('.', '/'); private JavaPsiFacade myJavaPsiFacade; private InferredAnnotationsManager myInferredAnnotationsManager; + private BytecodeAnalysisConverter myBytecodeAnalysisConverter; @Override protected void setUp() throws Exception { super.setUp(); myJavaPsiFacade = JavaPsiFacade.getInstance(myModule.getProject()); myInferredAnnotationsManager = InferredAnnotationsManager.getInstance(myModule.getProject()); + myBytecodeAnalysisConverter = BytecodeAnalysisConverter.getInstance(); + + setUpDataClasses(); } + @Override + protected void tearDown() throws Exception { + myBytecodeAnalysisConverter.disposeComponent(); + super.tearDown(); + } + + // TODO - test it, possible solution - via external annotation manager?? /* public void testVelocityJar() { VirtualFile lib = LocalFileSystem.getInstance().refreshAndFindFileByPath(PathManagerEx.getTestDataPath() + "/../../../lib"); @@ -60,15 +78,22 @@ public class BytecodeAnalysisTest extends JavaCodeInsightFixtureTestCase { } */ - public void testDataClasses() throws IOException { - VirtualFile dataClassesDir = setUpDataClasses(); - PsiTestUtil.addLibrary(myModule, "dataClasses", dataClassesDir.getPath(), new String[]{""}, ArrayUtil.EMPTY_STRING_ARRAY); - //PsiClass psiClass = myJavaPsiFacade.findClass(Test01.class.getName(), GlobalSearchScope.moduleWithLibrariesScope(myModule)); - //assertNotNull(psiClass); + public void testInference() throws IOException { checkAnnotations(Test01.class); } + public void testCompoundKeys() throws IOException { + checkCompoundIds(Test01.class); + checkCompoundIds(Test02.class); + checkCompoundIds(Test02.Inner1.class); + checkCompoundIds(Test02.Inner2.class); + checkCompoundIds(Test03.class); + checkCompoundIds(Test03.Inner1.class); + checkCompoundIds(Test03.Inner2.class); + checkCompoundIds(TestAnnotation.class); + } + private void checkAnnotations(Class javaClass) { PsiClass psiClass = myJavaPsiFacade.findClass(javaClass.getName(), GlobalSearchScope.moduleWithLibrariesScope(myModule)); assertNotNull(psiClass); @@ -111,13 +136,59 @@ public class BytecodeAnalysisTest extends JavaCodeInsightFixtureTestCase { } } - private VirtualFile setUpDataClasses() throws IOException { + private void checkCompoundIds(Class javaClass) throws IOException { + String javaClassName = javaClass.getCanonicalName(); + System.out.println(javaClassName); + PsiClass psiClass = myJavaPsiFacade.findClass(javaClassName, GlobalSearchScope.moduleWithLibrariesScope(myModule)); + assertNotNull(psiClass); + + for (java.lang.reflect.Method javaMethod : javaClass.getDeclaredMethods()) { + System.out.println(javaMethod.getName()); + Method method = new Method(Type.getDescriptor(javaClass), javaMethod.getName(), Type.getMethodDescriptor(javaMethod)); + boolean noKey = javaMethod.getAnnotation(ExpectNoPsiKey.class) != null; + PsiMethod psiMethod = psiClass.findMethodsByName(javaMethod.getName(), false)[0]; + checkCompoundId(method, psiMethod, noKey); + } + + for (Constructor constructor : javaClass.getDeclaredConstructors()) { + Method method = new Method(Type.getDescriptor(javaClass), "", Type.getConstructorDescriptor(constructor)); + boolean noKey = constructor.getAnnotation(ExpectNoPsiKey.class) != null; + PsiMethod[] constructors = psiClass.getConstructors(); + PsiMethod psiMethod = constructors[0]; + checkCompoundId(method, psiMethod, noKey); + } + } + + private void checkCompoundId(Method method, PsiMethod psiMethod, boolean noKey) throws IOException { + Direction direction = new Out(); + int[] psiKey = myBytecodeAnalysisConverter.mkCompoundKey(psiMethod, direction); + if (noKey) { + assertNull(psiKey); + return; + } + else { + assertNotNull(psiKey); + } + + int[] asmKey = myBytecodeAnalysisConverter.mkCompoundKey(new Key(method, direction)); + + System.out.println(Arrays.toString(asmKey)); + System.out.println(Arrays.toString(psiKey)); + + System.out.println(myBytecodeAnalysisConverter.showCompoundKey(asmKey)); + System.out.println(myBytecodeAnalysisConverter.showCompoundKey(psiKey)); + + Assert.assertArrayEquals(asmKey, psiKey); + } + + private void setUpDataClasses() throws IOException { File classesDir = new File(Test01.class.getResource(".").getFile()); File destDir = new File(myModule.getProject().getBaseDir().getPath() + myClassesProjectRelativePath); FileUtil.copyDir(classesDir, destDir); VirtualFile vFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(destDir); assertNotNull(vFile); - return vFile; + + PsiTestUtil.addLibrary(myModule, "dataClasses", vFile.getPath(), new String[]{""}, ArrayUtil.EMPTY_STRING_ARRAY); } } diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/bytecodeAnalysis/ExpectNoPsiKey.java b/java/java-tests/testSrc/com/intellij/codeInspection/bytecodeAnalysis/ExpectNoPsiKey.java new file mode 100644 index 000000000000..dde06c0f153b --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/codeInspection/bytecodeAnalysis/ExpectNoPsiKey.java @@ -0,0 +1,26 @@ +/* + * 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.codeInspection.bytecodeAnalysis; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * @author lambdamix + */ +@Retention(RetentionPolicy.RUNTIME) +public @interface ExpectNoPsiKey { +} diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/bytecodeAnalysis/data/Test02.java b/java/java-tests/testSrc/com/intellij/codeInspection/bytecodeAnalysis/data/Test02.java new file mode 100644 index 000000000000..50d8d2711803 --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/codeInspection/bytecodeAnalysis/data/Test02.java @@ -0,0 +1,54 @@ +/* + * 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.codeInspection.bytecodeAnalysis.data; + +import com.intellij.codeInspection.bytecodeAnalysis.BytecodeAnalysisConverter; +import com.intellij.codeInspection.bytecodeAnalysis.ExpectNoPsiKey; + +/** + * @author lambdamix + */ +public class Test02 { + + public static class Inner1 { + public Inner1(Object o) { + + } + public Inner1[] Inner1test01(Inner1[] tests, Inner1... ellipsis) { + return tests; + } + } + + public class Inner2 { + public Inner2(Object o) { + + } + public Inner2[] Inner2test01(Inner2[] tests, Inner2... ellipsis) { + return tests; + } + } + + public Test02(int x) {} + + @ExpectNoPsiKey + public BytecodeAnalysisConverter.InternalKey test01(BytecodeAnalysisConverter.InternalKey converter) { + return converter; + } + + public Test02[] test02(Test02[] tests) { + return tests; + } +} diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/bytecodeAnalysis/data/Test03.java b/java/java-tests/testSrc/com/intellij/codeInspection/bytecodeAnalysis/data/Test03.java new file mode 100644 index 000000000000..f2d0967fc385 --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/codeInspection/bytecodeAnalysis/data/Test03.java @@ -0,0 +1,54 @@ +/* + * 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.codeInspection.bytecodeAnalysis.data; + +import com.intellij.codeInspection.bytecodeAnalysis.BytecodeAnalysisConverter; +import com.intellij.codeInspection.bytecodeAnalysis.ExpectNoPsiKey; + +/** + * @author lambdamix + */ +public class Test03 { + + public static class Inner1 { + public Inner1(Object o) { + + } + public Inner1[] Inner1test01(Inner1[] tests, Inner1... ellipsis) { + return tests; + } + } + + public class Inner2 { + public Inner2(A o) { + + } + public A[] Inner2test01(A[] tests, A... ellipsis) { + return tests; + } + } + + public Test03(@TestAnnotation int x) {} + + @ExpectNoPsiKey + public BytecodeAnalysisConverter.InternalKey test01(BytecodeAnalysisConverter.InternalKey converter) { + return converter; + } + + public Test03[] test02(Test03[] tests) { + return tests; + } +} diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/bytecodeAnalysis/data/TestAnnotation.java b/java/java-tests/testSrc/com/intellij/codeInspection/bytecodeAnalysis/data/TestAnnotation.java new file mode 100644 index 000000000000..cfe55ff5cd28 --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/codeInspection/bytecodeAnalysis/data/TestAnnotation.java @@ -0,0 +1,26 @@ +/* + * 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.codeInspection.bytecodeAnalysis.data; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * @author lambdamix + */ +@Retention(RetentionPolicy.RUNTIME) +public @interface TestAnnotation { +}