From 8c20a632da455833e1603b0a645757dd80e14ac9 Mon Sep 17 00:00:00 2001 From: Sebastian Zarnekow Date: Tue, 9 Jun 2015 14:37:09 +0300 Subject: [PATCH] Fixed generic type references when read from cls files (IDEA-141230) https://github.com/JetBrains/intellij-community/pull/273 --- .../ClsJavaCodeReferenceElementImpl.java | 27 ++++++++-- .../ParameterizedTypes$Inner.class | Bin 0 -> 614 bytes .../genericSignature/ParameterizedTypes.class | Bin 0 -> 744 bytes .../psi/resolve/ResolveInLibrariesTest.groovy | 49 ++++++++++++++++++ 4 files changed, 73 insertions(+), 3 deletions(-) create mode 100644 java/java-tests/testData/libResolve/genericSignature/ParameterizedTypes$Inner.class create mode 100644 java/java-tests/testData/libResolve/genericSignature/ParameterizedTypes.class diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsJavaCodeReferenceElementImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsJavaCodeReferenceElementImpl.java index 4d713b0e4f52..89eddafc52f9 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsJavaCodeReferenceElementImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsJavaCodeReferenceElementImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -17,7 +17,6 @@ package com.intellij.psi.impl.compiled; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.TextRange; -import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.impl.PsiSubstitutorImpl; import com.intellij.psi.impl.ResolveScopeManager; @@ -33,6 +32,7 @@ import com.intellij.psi.util.PsiUtil; import com.intellij.psi.util.TypeConversionUtil; import com.intellij.util.IncorrectOperationException; import com.intellij.util.containers.HashMap; +import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -143,7 +143,7 @@ public class ClsJavaCodeReferenceElementImpl extends ClsElementImpl implements P final Map substitutionMap) { final PsiClass containingClass = psiClass.getContainingClass(); if (containingClass != null && !containingClass.hasModifierProperty(PsiModifier.STATIC)) { - final String outerClassRef = StringUtil.getPackageName(canonicalText); + final String outerClassRef = getOuterClassRef(canonicalText); final String[] classParameters = PsiNameHelper.getClassParametersText(outerClassRef); final PsiType[] args = classParameters.length == 0 ? null : new ClsReferenceParameterListImpl(this, classParameters).getTypeArguments(); final PsiTypeParameter[] typeParameters = containingClass.getTypeParameters(); @@ -156,6 +156,27 @@ public class ClsJavaCodeReferenceElementImpl extends ClsElementImpl implements P } } + @NotNull + @Contract(pure = true) + private static String getOuterClassRef(String ref) { + int stack = 0; + for (int i = ref.length() - 1; i >= 0; i--) { + char c = ref.charAt(i); + switch (c) { + case '<': + stack--; + break; + case '>': + stack++; + break; + case '.': + if (stack == 0) return ref.substring(0, i); + } + } + + return ""; + } + @Override @NotNull public JavaResolveResult advancedResolve(boolean incompleteCode) { diff --git a/java/java-tests/testData/libResolve/genericSignature/ParameterizedTypes$Inner.class b/java/java-tests/testData/libResolve/genericSignature/ParameterizedTypes$Inner.class new file mode 100644 index 0000000000000000000000000000000000000000..0833dec8203bd01d94385889028834ca28fe2dd3 GIT binary patch literal 614 zcmZ`$!A`G=I3OnA!IN!zAu%Col!S)+0vlW`g|x*)|H^|g@!$ve zQO0TEqChs8**AIf=I!kF&*v9_8=PgKpr}JdNyCYTQ-)0RD8t${L)n=>jaywF@TrJI zAYaAEeVL2UB#tG08QBb#`Zm&KpFwTUMuH*dNMGD9rUMbUeBe=~;LL{H>+?XycvV#6 z!3^n+?~8!JNOIfbVJN74zGYA?p^>NJUrlnl(%oj!a=WJ8Oxi8CW7?#V?a8svqeVa- z>sII1neb=c^0+^4Jq#vd7@78Zi9zqp7Qs;5$@p!h^^G-S83So#3}~oms4`SHFL(JI zhW!7@3`#xTX>oI(dO;tl(x0+?J{}a`=xErXm?hLjiVmPRuHL~KA4t6sQlL}J5C_z? rOR>0Q!9b1>@e?&NM0X?M>68x$DJW1(;SfhjKE^&}oj3~0*i+dra)gwn literal 0 HcmV?d00001 diff --git a/java/java-tests/testData/libResolve/genericSignature/ParameterizedTypes.class b/java/java-tests/testData/libResolve/genericSignature/ParameterizedTypes.class new file mode 100644 index 0000000000000000000000000000000000000000..10117a15dbe6b42c97973794e56b2de659b0789d GIT binary patch literal 744 zcmaJSkq^>)uob-S->QJ zW5eF-l=*D}rDYkSb7?I>WAwUh6NN>W1rNfXGKW8MXFmIJy^$b0jTorQ+T0a1m`R-Z zB9R_-X+|2u8qpWp@~CiIb|ATMqy7c#Z!dShNw!;uSqRMzp-kseYNP+=3_axn?x7G~Q^NFI;|1=vAO5i2R!#e8oe-$$poQi5{C Ps6YmzjtT|&szQDN+-AU~ literal 0 HcmV?d00001 diff --git a/java/java-tests/testSrc/com/intellij/psi/resolve/ResolveInLibrariesTest.groovy b/java/java-tests/testSrc/com/intellij/psi/resolve/ResolveInLibrariesTest.groovy index ce5c6575fb86..b2394a8e763e 100644 --- a/java/java-tests/testSrc/com/intellij/psi/resolve/ResolveInLibrariesTest.groovy +++ b/java/java-tests/testSrc/com/intellij/psi/resolve/ResolveInLibrariesTest.groovy @@ -22,7 +22,9 @@ import com.intellij.openapi.vfs.LocalFileSystem import com.intellij.openapi.vfs.VirtualFile import com.intellij.psi.JavaPsiFacade import com.intellij.psi.PsiClass +import com.intellij.psi.PsiClassType import com.intellij.psi.PsiMethod +import com.intellij.psi.impl.JavaPsiFacadeEx import com.intellij.psi.impl.source.PsiFileImpl import com.intellij.psi.search.GlobalSearchScope import com.intellij.psi.search.searches.ClassInheritorsSearch @@ -236,4 +238,51 @@ class TestCase { assert method.hierarchicalMethodSignature.superSignatures.size() == 0 } + public void "test nested generic signature from binary"() { + myFixture.testDataPath = PathManagerEx.getTestDataPath() + "/libResolve/genericSignature" + myFixture.copyDirectoryToProject("", "lib") + PsiTestUtil.addLibrary(myModule, "lib", myFixture.tempDirFixture.getFile("").path, "lib"); + + def javaPsiFacade = JavaPsiFacadeEx.getInstanceEx(project) + def factory = javaPsiFacade.elementFactory + + def parameterizedTypes = JavaPsiFacade.getInstance(project).findClass('pkg.ParameterizedTypes', GlobalSearchScope.allScope(project)) + assert parameterizedTypes + + def parameterP = parameterizedTypes.typeParameters[0] + assert parameterP.name == 'P' + + def classInner = parameterizedTypes.innerClasses[0] + assert classInner.name == 'Inner' + + def parameterI = classInner.typeParameters[0] + assert parameterI.name == 'I' + + def unspecificMethod = parameterizedTypes.findMethodsByName("getUnspecificInner", false)[0] + def unspecificReturnType = unspecificMethod.returnType as PsiClassType + assert unspecificReturnType.canonicalText == 'pkg.ParameterizedTypes

.Inner' + + def unspecificResolveResult = unspecificReturnType.resolveGenerics() + assert unspecificResolveResult.element == classInner + + def unspecificOuter = factory.createType(parameterizedTypes, unspecificResolveResult.substitutor); + assert unspecificOuter.canonicalText == 'pkg.ParameterizedTypes

' + + def specificMethod = parameterizedTypes.findMethodsByName("getSpecificInner", false)[0] + def specificReturnType = specificMethod.returnType as PsiClassType + assert specificReturnType.canonicalText == 'pkg.ParameterizedTypes.Inner' + + def specificResolveResult = specificReturnType.resolveGenerics() + assert specificResolveResult.element == classInner + + def substitutor = specificResolveResult.substitutor + def substitutionMap = substitutor.substitutionMap + assert substitutionMap.containsKey(parameterI) + assert substitutionMap.containsKey(parameterP) + assert substitutor.substitute(parameterP).canonicalText == 'java.lang.Number' + + def specificOuter = factory.createType(parameterizedTypes, specificResolveResult.substitutor); + assert specificOuter.canonicalText == 'pkg.ParameterizedTypes' + } + }