blob: ce04dd0ba20c0cf89716aa01725559ede756555c [file] [log] [blame]
/*
* Copyright 2000-2012 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.resolve
import com.intellij.openapi.application.ex.PathManagerEx
import com.intellij.openapi.vfs.JarFileSystem
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.PsiMethod
import com.intellij.psi.impl.source.PsiFileImpl
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.search.searches.ClassInheritorsSearch
import com.intellij.psi.search.searches.OverridingMethodsSearch
import com.intellij.psi.stubs.StubTreeLoader
import com.intellij.testFramework.PsiTestUtil
import com.intellij.testFramework.fixtures.JavaCodeInsightFixtureTestCase
/**
* @author peter
*/
class ResolveInLibrariesTest extends JavaCodeInsightFixtureTestCase {
public void "test prefer current library when navigation from its source"() {
def lib = LocalFileSystem.getInstance().refreshAndFindFileByPath(PathManagerEx.getTestDataPath() + "/../../../lib")
def nanoJar = lib.children.find { it.name.startsWith("nanoxml") }
def nanoSrc = lib.findChild("src").children.find { it.name.startsWith("nanoxml") }
def jarCopy = myFixture.copyFileToProject(nanoJar.path, 'lib/nanoJar.jar')
def srcCopy = myFixture.copyFileToProject(nanoSrc.path, 'lib/nanoSrc.zip')
PsiTestUtil.addLibrary(myModule, 'nano1', lib.path, ["/$nanoJar.name!/"] as String[], ["/src/$nanoSrc.name!/"] as String[])
PsiTestUtil.addLibrary(myModule, 'nano2', jarCopy.parent.path, ["/$jarCopy.name!/"] as String[], ["/$srcCopy.name!/"] as String[])
def parsers = JavaPsiFacade.getInstance(project).findClasses('net.n3.nanoxml.IXMLParser', GlobalSearchScope.allScope(project))
assert parsers.size() == 2
def file0 = parsers[0].navigationElement.containingFile
assert file0.virtualFile.path.startsWith(nanoSrc.path)
assert file0.findReferenceAt(file0.text.indexOf('IXMLReader reader')).resolve().navigationElement.containingFile.virtualFile.path.startsWith(nanoSrc.path)
def file1 = parsers[1].navigationElement.containingFile
assert file1.virtualFile.path.startsWith(srcCopy.path)
assert file1.findReferenceAt(file1.text.indexOf('IXMLReader reader')).resolve().navigationElement.containingFile.virtualFile.path.startsWith(srcCopy.path)
}
public void "test inheritance transitivity"() {
def lib = LocalFileSystem.getInstance().refreshAndFindFileByPath(PathManagerEx.getTestDataPath() + "/../../../lib")
def protoJar = lib.children.find { it.name.startsWith("protobuf") }
def jarCopy = myFixture.copyFileToProject(protoJar.path, 'lib/protoJar.jar')
PsiTestUtil.addLibrary(myModule, 'proto1', lib.path, ["/$protoJar.name!/"] as String[], [] as String[])
PsiTestUtil.addLibrary(myModule, 'proto2', jarCopy.parent.path, ["/$jarCopy.name!/"] as String[], [] as String[])
def scope = GlobalSearchScope.allScope(project)
def bottoms = JavaPsiFacade.getInstance(project).findClasses('com.google.protobuf.AbstractMessage', scope)
assert bottoms.size() == 2
def middles = JavaPsiFacade.getInstance(project).findClasses('com.google.protobuf.AbstractMessageLite', scope)
assert middles.size() == 2
def intfs = JavaPsiFacade.getInstance(project).findClasses('com.google.protobuf.MessageLite', scope)
assert intfs.size() == 2
for (i in 0..1) {
assert ClassInheritorsSearch.search(intfs[i]).findAll().containsAll([middles[i], bottoms[i]])
intfs[i].methods.each {
assert OverridingMethodsSearch.search(it).findAll()
}
assert middles[i].isInheritor(intfs[i], true)
assert bottoms[i].isInheritor(intfs[i], true)
assert bottoms[i].isInheritor(middles[i], true)
}
}
public void "test accept that with different library versions inheritance relation may be intransitive"() {
def lib = LocalFileSystem.getInstance().refreshAndFindFileByPath(PathManagerEx.getTestDataPath() + "/libResolve/inheritance")
//Foo, Middle implements Foo, Other extends Middle
PsiTestUtil.addLibrary(myModule, 'full', lib.path, ["/fullLibrary.jar!/"] as String[], [] as String[])
//Middle, Bottom extends Middle
PsiTestUtil.addLibrary(myModule, 'partial', lib.path, ["/middleBottom.jar!/"] as String[], [] as String[])
def scope = GlobalSearchScope.allScope(project)
def i0 = JavaPsiFacade.getInstance(project).findClass('Intf', scope)
def other0 = JavaPsiFacade.getInstance(project).findClass('Other', scope)
def b1 = JavaPsiFacade.getInstance(project).findClass('Bottom', scope)
def middles = JavaPsiFacade.getInstance(project).findClasses('Middle', scope)
assert middles.size() == 2
def m0 = middles[0]
def m1 = middles[1]
for (deep in [false, true]) {
assert m0.isInheritor(i0, deep)
assert other0.isInheritor(m0, deep)
assert !b1.isInheritor(i0, deep)
assert b1.isInheritor(m0, deep)
assert b1.isInheritor(m1, deep)
assert !m1.isInheritor(i0, deep)
}
assert other0.isInheritor(i0, true)
assert !other0.isInheritor(i0, false)
assert ClassInheritorsSearch.search(i0).findAll() == [m0, b1, other0] as Set
assert ClassInheritorsSearch.search(m0).findAll() == [b1, other0] as Set
assert fooInheritors(i0) == [fooMethod(m0), fooMethod(other0)] as Set
assert fooInheritors(m0) == [fooMethod(other0), fooMethod(b1)] as Set
assert fooInheritors(m1) == [fooMethod(other0), fooMethod(b1)] as Set
}
private static PsiMethod fooMethod(PsiClass c) { c.findMethodsByName('foo', false)[0] }
private static Set<PsiMethod> fooInheritors(PsiClass c) { OverridingMethodsSearch.search(fooMethod(c)).findAll() as Set }
public void "test do not parse not stubbed sources in class jars"() {
def lib = LocalFileSystem.getInstance().refreshAndFindFileByPath(PathManagerEx.getTestDataPath() + "/libResolve/classesAndSources")
PsiTestUtil.addLibrary(myModule, 'cas', lib.path, ["/classesAndSources.jar!/"] as String[], ["/classesAndSources.jar!/"] as String[])
def facade = JavaPsiFacade.getInstance(project)
def scope = GlobalSearchScope.allScope(project)
assert facade.findClasses('LibraryClass', scope).size() == 1
def pkg = facade.findPackage("")
assert pkg.classes.size() == 1
Collection<VirtualFile> pkgDirs = pkg.directories.collect { it.virtualFile }
Collection<VirtualFile> pkgChildren = pkgDirs.collect { it.children as List }.flatten()
VirtualFile javaSrc = pkgChildren.find { it.name == 'LibraryClass.java' }
checkFileIsNotLoadedAndHasNoIndexedStub(javaSrc)
assert pkg.containsClassNamed('LibraryClass')
checkFileIsNotLoadedAndHasNoIndexedStub(javaSrc)
assert !((PsiFileImpl)psiManager.findFile(javaSrc)).treeElement
}
@Override
protected boolean toAddSourceRoot() {
return false;
}
public void "test do not build stubs in source jars"() {
def facade = JavaPsiFacade.getInstance(project)
def scope = GlobalSearchScope.allScope(project)
String testDataPathForTest = PathManagerEx.getTestDataPath() + "/libResolve/classesAndSources"
def lib = LocalFileSystem.getInstance().refreshAndFindFileByPath(testDataPathForTest)
def localFile = myFixture.copyFileToProject(testDataPathForTest + File.separator + "Foo.java", 'Foo.java')
assert localFile != null
checkFileIsNotLoadedAndHasNoIndexedStub(localFile)
assert facade.findClasses('Foo', scope).size() == 0
PsiTestUtil.addLibrary(myModule, 'cas', lib.path, [] as String[], ["/classesAndSources.jar!/"] as String[])
def vfile = lib.findChild("classesAndSources.jar")
assert vfile != null
vfile = JarFileSystem.getInstance().getJarRootForLocalFile(vfile);
assert vfile != null
vfile = vfile.findChild('LibraryClass.java');
assert vfile != null
assert facade.findClasses('LibraryClass', scope).size() == 0
checkFileIsNotLoadedAndHasNoIndexedStub(vfile)
}
private void checkFileIsNotLoadedAndHasNoIndexedStub(VirtualFile vfile) {
PsiFileImpl file = psiManager.findFile(vfile);
assert file != null
assert !file.contentsLoaded
assert !StubTreeLoader.instance.readFromVFile(project, vfile)
assert !StubTreeLoader.instance.canHaveStub(vfile)
assert file.stub // from text
}
}