| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you 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 org.netbeans.modules.java.source.ui; |
| |
| import org.netbeans.api.java.source.*; |
| import java.beans.PropertyChangeListener; |
| import java.beans.PropertyChangeSupport; |
| import java.io.File; |
| import java.io.IOException; |
| import java.io.OutputStreamWriter; |
| import java.io.PrintWriter; |
| import java.net.URL; |
| import java.util.*; |
| import javax.swing.event.ChangeListener; |
| import org.netbeans.api.java.classpath.ClassPath; |
| import org.netbeans.api.java.platform.JavaPlatformManager; |
| import org.netbeans.api.java.queries.SourceForBinaryQuery; |
| import org.netbeans.junit.MockServices; |
| import org.netbeans.junit.NbTestCase; |
| import org.netbeans.modules.java.source.parsing.FileObjects; |
| import org.netbeans.modules.java.source.ui.JavaTypeProvider; |
| import org.netbeans.modules.java.source.usages.IndexUtil; |
| import org.netbeans.modules.parsing.api.indexing.IndexingManager; |
| import org.netbeans.spi.java.classpath.ClassPathFactory; |
| import org.netbeans.spi.java.classpath.ClassPathImplementation; |
| import org.netbeans.spi.java.classpath.ClassPathProvider; |
| import org.netbeans.spi.java.classpath.PathResourceImplementation; |
| import org.netbeans.spi.java.classpath.support.ClassPathSupport; |
| import org.netbeans.spi.java.queries.SourceForBinaryQueryImplementation; |
| import org.netbeans.spi.jumpto.type.JumptoAccessor; |
| import org.netbeans.spi.jumpto.type.SearchType; |
| import org.netbeans.spi.jumpto.type.TypeDescriptor; |
| import org.netbeans.spi.jumpto.type.TypeProvider; |
| import org.openide.filesystems.FileLock; |
| import org.openide.filesystems.FileObject; |
| import org.openide.filesystems.FileStateInvalidException; |
| import org.openide.filesystems.FileUtil; |
| |
| /** |
| * Test setup taken from org.netbeans.api.java.source.ClassIndexTest. |
| * |
| * @author Tomas Zezula |
| * @author markiewb |
| */ |
| public class JavaTypeProviderTest extends NbTestCase { |
| |
| private static FileObject srcRoot; |
| private static FileObject binRoot2; |
| private static FileObject libSrc2; |
| private static ClassPath sourcePath; |
| private static ClassPath compilePath; |
| private static ClassPath bootPath; |
| private static JavaTypeProviderTest.MutableCp spiCp; |
| private static JavaTypeProviderTest.MutableCp spiSrc; |
| private JavaTypeProvider provider; |
| |
| public JavaTypeProviderTest(String name) { |
| super(name); |
| } |
| String[] cA = {"ClassA", "org.me.pkg1"}; |
| String[] cB = {"ClassA", "org.me.pkg1sibling"}; |
| String[] cC = {"ClassA", "org.me.pkg1.subpackage"}; |
| String[] cD = {"ClassB", "org.me.pkg2"}; |
| String[] cE = {"ClassA", "com.other"}; |
| String[] cF = {"ClassB", "org.me.pkg1.subpackage"}; |
| |
| @Override |
| protected void setUp() throws Exception { |
| clearWorkDir(); |
| File cache = new File(getWorkDir(), "cache"); //NOI18N |
| cache.mkdirs(); |
| IndexUtil.setCacheFolder(cache); |
| File src = new File(getWorkDir(), "src"); //NOI18N |
| src.mkdirs(); |
| srcRoot = FileUtil.toFileObject(src); |
| srcRoot.createFolder("foo"); //NOI18N |
| src = new File(getWorkDir(), "src2"); //NOI18N |
| src.mkdirs(); |
| src = new File(getWorkDir(), "lib"); //NOI18N |
| src.mkdirs(); |
| src = new File(getWorkDir(), "lib2"); //NOI18N |
| src.mkdirs(); |
| binRoot2 = FileUtil.toFileObject(src); |
| src = new File(getWorkDir(), "lib2Src"); //NOI18N |
| src.mkdirs(); |
| libSrc2 = FileUtil.toFileObject(src); |
| spiSrc = new JavaTypeProviderTest.MutableCp(Collections.singletonList(ClassPathSupport.createResource(srcRoot.getURL()))); |
| sourcePath = ClassPathFactory.createClassPath(spiSrc); |
| spiCp = new JavaTypeProviderTest.MutableCp(); |
| compilePath = ClassPathFactory.createClassPath(spiCp); |
| bootPath = JavaPlatformManager.getDefault().getDefaultPlatform().getBootstrapLibraries(); |
| MockServices.setServices(JavaTypeProviderTest.ClassPathProviderImpl.class, JavaTypeProviderTest.SFBQ.class); |
| |
| //create some types to be searched for later |
| String[][] testTypes = { |
| cA, cB, cC, cD, cE, cF |
| }; |
| |
| for (String[] entry : testTypes) { |
| createJavaFile(srcRoot, entry[1], entry[0]); |
| } |
| IndexingManager.getDefault().refreshIndexAndWait(srcRoot.getURL(), null, true); |
| final ClassPath scp = ClassPathSupport.createClassPath(srcRoot); |
| final ClasspathInfo cpInfo = ClasspathInfo.create( |
| ClassPathSupport.createClassPath(new URL[0]), |
| ClassPathSupport.createClassPath(new URL[0]), |
| scp); |
| provider = new JavaTypeProvider(cpInfo, null); |
| |
| } |
| |
| @Override |
| protected void tearDown() throws Exception { |
| MockServices.setServices(); |
| } |
| |
| |
| /** |
| * Tests the behaviour, when no package name is included in searchText. |
| * Packagenames should be ignored. |
| * |
| * @throws Exception |
| */ |
| public void testGetDeclaredTypesScopes_DefaultBehaviour() throws Exception { |
| //original behaviour - without packagename |
| { |
| String[][] expectedResults = {cE, cA, cC, cB}; |
| assertComputeTypeNames(expectedResults, "ClassA", provider); |
| } |
| //original behaviour - without packagename |
| { |
| String[][] expectedResults = {cF, cD}; |
| assertComputeTypeNames(expectedResults, "ClassB", provider); |
| } |
| |
| } |
| |
| /** |
| * A partially given FQN may result in more than one class type. The |
| * packagename is used for retrival of package and subpackages, which |
| * results in more results. |
| * |
| * @throws Exception |
| */ |
| public void testGetDeclaredTypesScopes_FullyQualifiedName() throws Exception { |
| //search for classes with prefix "ClassA" and packages with (sub-)package "org.me.pkg1" |
| { |
| String[][] expectedResults = {cA, cC, cB}; |
| assertComputeTypeNames(expectedResults, "org.me.pkg1.ClassA", provider); |
| } |
| //search for classes with prefix "ClassA" and packages with (sub-)package "org" |
| { |
| String[][] expectedResults = {cA, cC, cB}; |
| assertComputeTypeNames(expectedResults, "org.ClassA", provider); |
| } |
| //search for classes with prefix "ClassA" and packages with (sub-)package "org.me" |
| { |
| String[][] expectedResults = {cA, cC, cB}; |
| assertComputeTypeNames(expectedResults, "org.me.ClassA", provider); |
| } |
| //search for classes with prefix "Cl" and packages with (sub-)package "org.me" |
| { |
| String[][] expectedResults = {cA, cC, cB, cF, cD}; |
| assertComputeTypeNames(expectedResults, "org.me.Cl", provider); |
| } |
| //search for classes with prefix "Cl" and packages with (sub-)package "o*.m*" |
| { |
| String[][] expectedResults = {cA, cC, cB, cF, cD}; |
| assertComputeTypeNames(expectedResults, "o.m.Cl", provider); |
| } |
| //search for classes with camel case "CA" and packages with (sub-)package "o*.m*" |
| { |
| String[][] expectedResults = {cA, cC, cB}; |
| assertComputeTypeNames(expectedResults, "o.m.CA", provider); |
| } |
| //search for classes with camel case "CA" and packages with (sub-)package "o*.m*" |
| { |
| String[][] expectedResults = {cB}; |
| assertComputeTypeNames(expectedResults, "o.m.pkg1sib.CA", provider); |
| } |
| |
| } |
| |
| private FileObject createJavaFile( |
| final FileObject root, |
| final String pkg, |
| final String name, |
| final String content) throws IOException { |
| final FileObject file = FileUtil.createData( |
| root, |
| String.format("%s/%s.java", |
| FileObjects.convertPackage2Folder(pkg), |
| name)); |
| final FileLock lck = file.lock(); |
| try { |
| final PrintWriter out = new PrintWriter(new OutputStreamWriter(file.getOutputStream(lck))); |
| try { |
| out.print(content); |
| } finally { |
| out.close(); |
| } |
| } finally { |
| lck.releaseLock(); |
| } |
| return file; |
| } |
| |
| private void assertComputeTypeNames(String[][] expectedResults, String searchText, TypeProvider provider) { |
| List<TypeDescriptor> results = new ArrayList<TypeDescriptor>(); |
| TypeProvider.Context c = JumptoAccessor.createContext(null, searchText, SearchType.PREFIX); |
| TypeProvider.Result res = JumptoAccessor.createResult(results, c); |
| |
| provider.computeTypeNames(c, res); |
| |
| assertEquals(expectedResults.length, results.size()); |
| //sort to make the result test run reproducable |
| Collections.sort(results, new Comparator<TypeDescriptor>() { |
| @Override |
| public int compare(TypeDescriptor o1, TypeDescriptor o2) { |
| int compareValue = o1.getSimpleName().compareToIgnoreCase(o2.getSimpleName()); |
| if (compareValue != 0) { |
| return compareValue; |
| } |
| return o1.getContextName().compareToIgnoreCase(o2.getContextName()); |
| } |
| }); |
| |
| for (int i = 0; i < results.size(); i++) { |
| |
| assertEquals("not equals at index " + i, expectedResults[i][0], results.get(i).getSimpleName()); |
| assertEquals("not equals at index " + i, " (" + expectedResults[i][1] + ")", results.get(i).getContextName()); |
| } |
| } |
| |
| private FileObject createJavaFile(FileObject srcRoot1, String packageName, String className) throws IOException { |
| return createJavaFile(srcRoot1, packageName, className, "package " + packageName + ";\npublic class " + className + " {}\n"); |
| } |
| |
| public static class ClassPathProviderImpl implements ClassPathProvider { |
| |
| public ClassPath findClassPath(final FileObject file, final String type) { |
| final FileObject[] roots = sourcePath.getRoots(); |
| for (FileObject root : roots) { |
| if (root.equals(file) || FileUtil.isParentOf(root, file)) { |
| if (type == ClassPath.SOURCE) { |
| return sourcePath; |
| } |
| if (type == ClassPath.COMPILE) { |
| return compilePath; |
| } |
| if (type == ClassPath.BOOT) { |
| return bootPath; |
| } |
| } |
| } |
| if (libSrc2.equals(file) || FileUtil.isParentOf(libSrc2, file)) { |
| if (type == ClassPath.SOURCE) { |
| return ClassPathSupport.createClassPath(new FileObject[]{libSrc2}); |
| } |
| if (type == ClassPath.COMPILE) { |
| return ClassPathSupport.createClassPath(new URL[0]); |
| } |
| if (type == ClassPath.BOOT) { |
| return bootPath; |
| } |
| } |
| return null; |
| } |
| } |
| |
| public static class SFBQ implements SourceForBinaryQueryImplementation { |
| |
| public SourceForBinaryQuery.Result findSourceRoots(URL binaryRoot) { |
| try { |
| if (binaryRoot.equals(binRoot2.getURL())) { |
| return new SourceForBinaryQuery.Result() { |
| public FileObject[] getRoots() { |
| return new FileObject[]{libSrc2}; |
| } |
| |
| public void addChangeListener(ChangeListener l) { |
| } |
| |
| public void removeChangeListener(ChangeListener l) { |
| } |
| }; |
| } |
| } catch (FileStateInvalidException e) { |
| } |
| return null; |
| } |
| } |
| |
| private static final class MutableCp implements ClassPathImplementation { |
| |
| private final PropertyChangeSupport support; |
| private List<? extends PathResourceImplementation> impls; |
| |
| public MutableCp() { |
| this(Collections.<PathResourceImplementation>emptyList()); |
| } |
| |
| public MutableCp(final List<? extends PathResourceImplementation> impls) { |
| assert impls != null; |
| support = new PropertyChangeSupport(this); |
| this.impls = impls; |
| } |
| |
| public List<? extends PathResourceImplementation> getResources() { |
| return impls; |
| } |
| |
| public void addPropertyChangeListener(final PropertyChangeListener listener) { |
| assert listener != null; |
| this.support.addPropertyChangeListener(listener); |
| } |
| |
| public void removePropertyChangeListener(final PropertyChangeListener listener) { |
| assert listener != null; |
| this.support.removePropertyChangeListener(listener); |
| } |
| |
| void setImpls(final List<? extends PathResourceImplementation> impls) { |
| assert impls != null; |
| this.impls = impls; |
| this.support.firePropertyChange(PROP_RESOURCES, null, null); |
| } |
| } |
| } |