blob: 4fcb40296a4844f5e641639f670cd1499f4d0944 [file] [log] [blame]
/*
* 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.index;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.fileTypes.PlainTextFileType;
import com.intellij.openapi.util.Factory;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.impl.PsiManagerEx;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.PsiSearchHelper;
import com.intellij.testFramework.IdeaTestCase;
import com.intellij.testFramework.PlatformTestUtil;
import com.intellij.testFramework.PsiTestUtil;
import com.intellij.testFramework.SkipSlowTestLocally;
import com.intellij.util.indexing.MapIndexStorage;
import com.intellij.util.indexing.StorageException;
import com.intellij.util.io.*;
import org.jetbrains.annotations.NotNull;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.File;
import java.io.IOException;
import java.util.*;
/**
* @author Eugene Zhuravlev
* Date: Dec 12, 2007
*/
@SkipSlowTestLocally
public class IndexTest extends IdeaTestCase {
public void testUpdate() throws StorageException, IOException {
final File storageFile = FileUtil.createTempFile("indextest", "storage");
final File metaIndexFile = FileUtil.createTempFile("indextest_inputs", "storage");
final MapIndexStorage indexStorage = new MapIndexStorage(storageFile, new EnumeratorStringDescriptor(), new EnumeratorStringDescriptor(), 16 * 1024);
final StringIndex index = new StringIndex(indexStorage, new Factory<PersistentHashMap<Integer, Collection<String>>>() {
@Override
public PersistentHashMap<Integer, Collection<String>> create() {
try {
return createMetaIndex(metaIndexFile);
}
catch (IOException e) {
throw new RuntimeException(e);
}
}
});
try {
// build index
index.update("com/ppp/a.java", "a b c d", null);
index.update("com/ppp/b.java", "a b g h", null);
index.update("com/ppp/c.java", "a z f", null);
index.update("com/ppp/d.java", "a a u y z", null);
index.update("com/ppp/e.java", "a n chj e c d", null);
assertDataEquals(index.getFilesByWord("a"), "com/ppp/a.java", "com/ppp/b.java", "com/ppp/c.java", "com/ppp/d.java", "com/ppp/e.java");
assertDataEquals(index.getFilesByWord("b"), "com/ppp/a.java", "com/ppp/b.java");
assertDataEquals(index.getFilesByWord("c"), "com/ppp/a.java", "com/ppp/e.java");
assertDataEquals(index.getFilesByWord("d"), "com/ppp/a.java", "com/ppp/e.java");
assertDataEquals(index.getFilesByWord("g"), "com/ppp/b.java");
assertDataEquals(index.getFilesByWord("h"), "com/ppp/b.java");
assertDataEquals(index.getFilesByWord("z"), "com/ppp/c.java", "com/ppp/d.java");
assertDataEquals(index.getFilesByWord("f"), "com/ppp/c.java");
assertDataEquals(index.getFilesByWord("u"), "com/ppp/d.java");
assertDataEquals(index.getFilesByWord("y"), "com/ppp/d.java");
assertDataEquals(index.getFilesByWord("n"), "com/ppp/e.java");
assertDataEquals(index.getFilesByWord("chj"), "com/ppp/e.java");
assertDataEquals(index.getFilesByWord("e"), "com/ppp/e.java");
// update index
index.update("com/ppp/d.java", "a u y z", "a a u y z");
assertDataEquals(index.getFilesByWord("a"), "com/ppp/a.java", "com/ppp/b.java", "com/ppp/c.java", "com/ppp/d.java", "com/ppp/e.java");
index.update("com/ppp/d.java", "u y z", "a u y z");
assertDataEquals(index.getFilesByWord("a"), "com/ppp/a.java", "com/ppp/b.java", "com/ppp/c.java", "com/ppp/e.java");
index.update("com/ppp/d.java", "a a a u y z", "u y z");
assertDataEquals(index.getFilesByWord("a"), "com/ppp/a.java", "com/ppp/b.java", "com/ppp/c.java", "com/ppp/d.java", "com/ppp/e.java");
index.update("com/ppp/e.java", "a n chj e c d z", "a n chj e c d");
assertDataEquals(index.getFilesByWord("z"), "com/ppp/c.java", "com/ppp/d.java", "com/ppp/e.java");
index.update("com/ppp/b.java", null, "a b g h");
assertDataEquals(index.getFilesByWord("a"), "com/ppp/a.java", "com/ppp/c.java", "com/ppp/d.java", "com/ppp/e.java");
assertDataEquals(index.getFilesByWord("b"), "com/ppp/a.java");
assertDataEquals(index.getFilesByWord("g"));
assertDataEquals(index.getFilesByWord("h"));
}
finally {
indexStorage.close();
FileUtil.delete(storageFile);
}
}
private PersistentHashMap<Integer, Collection<String>> createMetaIndex(File metaIndexFile) throws IOException {
return new PersistentHashMap<Integer, Collection<String>>(metaIndexFile, new EnumeratorIntegerDescriptor(), new DataExternalizer<Collection<String>>() {
@Override
public void save(@NotNull DataOutput out, Collection<String> value) throws IOException {
DataInputOutputUtil.writeINT(out, value.size());
for (String key : value) {
out.writeUTF(key);
}
}
@Override
public Collection<String> read(@NotNull DataInput in) throws IOException {
final int size = DataInputOutputUtil.readINT(in);
final List<String> list = new ArrayList<String>();
for (int idx = 0; idx < size; idx++) {
list.add(in.readUTF());
}
return list;
}
});
}
/*
public void testStubIndexUnsavedDocumentsIndexing() throws IncorrectOperationException, IOException, StorageException {
IdeaTestUtil.registerExtension(StubIndexExtension.EP_NAME, new TextStubIndexExtension(), getTestRootDisposable());
IdeaTestUtil.registerExtension(StubIndexExtension.EP_NAME, new ClassNameStubIndexExtension(), getTestRootDisposable());
FileTypeManager.getInstance().registerFileType(TestFileType.INSTANCE, "fff");
final FFFLangParserDefinition parserDefinition = new FFFLangParserDefinition();
LanguageParserDefinitions.INSTANCE.addExplicitExtension(FFFLanguage.INSTANCE, parserDefinition);
final TestStubElementType stubType = new TestStubElementType();
SerializationManager.getInstance().registerSerializer(TestStubElement.class, stubType);
final File fffFile = new File(FileUtil.createTempDirectory("testing", "stubindex"), "MyClass.fff");
fffFile.createNewFile();
final VirtualFile vFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(fffFile);
assertNotNull(vFile);
assertEquals(TestFileType.INSTANCE, vFile.getFileType());
try {
final MockPsiFile psiFile = new MockPsiFile(vFile, MockPsiManager.getInstance(myProject));
final MockPsiClass cls = new MockPsiClass("com.company.MyClass");
psiFile.add(cls);
final MockPsiMethod aaaMethod = new MockPsiMethod("aaa");
cls.addMethod(aaaMethod);
final MockPsiMethod bbbMethod = new MockPsiMethod("bbb");
cls.addMethod(bbbMethod);
final PsiFileStubImpl fileStub = new PsiFileStubImpl(psiFile);
final TestStubElement clsStub = stubType.createStub(cls, fileStub);
stubType.createStub(aaaMethod, clsStub);
stubType.createStub(bbbMethod, clsStub);
final ByteArrayOutputStream arrayStream = new ByteArrayOutputStream();
SerializationManager.getInstance().serialize(fileStub, new DataOutputStream(arrayStream));
final FileBasedIndex fbi = FileBasedIndex.getInstance();
final UpdatableIndex<Integer, SerializedStubTree, FileContent> stubUpdatingIndex = fbi.getIndex(StubUpdatingIndex.INDEX_ID);
final MemoryIndexStorage storage = (MemoryIndexStorage)((MapReduceIndex)stubUpdatingIndex).getStorage();
// initial
final int fileId = FileBasedIndex.getFileId(vFile);
final byte[] bytes = arrayStream.toByteArray();
stubUpdatingIndex.update(fileId, new FileContent(vFile, bytes), null);
final ValueContainer<SerializedStubTree> data = stubUpdatingIndex.getData(fileId);
final List<SerializedStubTree> trees = data.toValueList();
final SerializedStubTree tree = assertOneElement(trees);
assertTrue(Comparing.equal(bytes, tree.getBytes()));
final StubElement deserialized = tree.getStub();
}
finally {
LanguageParserDefinitions.INSTANCE.removeExplicitExtension(FFFLanguage.INSTANCE, parserDefinition);
}
}
*/
private static <T> void assertDataEquals(List<T> actual, T... expected) {
assertTrue(new HashSet<T>(Arrays.asList(expected)).equals(new HashSet<T>(actual)));
}
public void testCollectedPsiWithChangedDocument() throws IOException {
VirtualFile dir = getVirtualFile(createTempDirectory());
PsiTestUtil.addSourceContentToRoots(myModule, dir);
final VirtualFile vFile = createChildData(dir, "Foo.java");
VfsUtil.saveText(vFile, "class Foo {}");
final GlobalSearchScope scope = GlobalSearchScope.allScope(getProject());
final JavaPsiFacade facade = JavaPsiFacade.getInstance(getProject());
assertNotNull(facade.findClass("Foo", scope));
WriteCommandAction.runWriteCommandAction(null, new Runnable() {
@Override
public void run() {
PsiFile psiFile = PsiManager.getInstance(getProject()).findFile(vFile);
assertNotNull(psiFile);
Document document = FileDocumentManager.getInstance().getDocument(vFile);
document.deleteString(0, document.getTextLength());
assertNotNull(facade.findClass("Foo", scope));
psiFile = null;
PlatformTestUtil.tryGcSoftlyReachableObjects();
assertNull(((PsiManagerEx)PsiManager.getInstance(getProject())).getFileManager().getCachedPsiFile(vFile));
PsiClass foo = facade.findClass("Foo", scope);
assertNotNull(foo);
assertTrue(foo.isValid());
assertEquals("class Foo {}", foo.getText());
assertTrue(foo.isValid());
PsiDocumentManager.getInstance(myProject).commitAllDocuments();
assertNull(facade.findClass("Foo", scope));
}
});
}
public void testSavedUncommittedDocument() throws IOException {
VirtualFile dir = getVirtualFile(createTempDirectory());
PsiTestUtil.addSourceContentToRoots(myModule, dir);
final VirtualFile vFile = createChildData(dir, "Foo.java");
VfsUtil.saveText(vFile, "");
final GlobalSearchScope scope = GlobalSearchScope.allScope(getProject());
final JavaPsiFacade facade = JavaPsiFacade.getInstance(getProject());
assertNull(facade.findClass("Foo", scope));
WriteCommandAction.runWriteCommandAction(null, new Runnable() {
@Override
public void run() {
PsiFile psiFile = PsiManager.getInstance(getProject()).findFile(vFile);
assertNotNull(psiFile);
long count = PsiManager.getInstance(myProject).getModificationTracker().getModificationCount();
Document document = FileDocumentManager.getInstance().getDocument(vFile);
document.insertString(0, "class Foo {}");
FileDocumentManager.getInstance().saveDocument(document);
assertTrue(count == PsiManager.getInstance(myProject).getModificationTracker().getModificationCount());
assertNull(facade.findClass("Foo", scope));
PsiDocumentManager.getInstance(myProject).commitAllDocuments();
assertNotNull(facade.findClass("Foo", scope));
assertNotNull(facade.findClass("Foo", scope).getText());
// if Foo exists now, mod count should be different
assertTrue(count != PsiManager.getInstance(myProject).getModificationTracker().getModificationCount());
}
});
}
public void testSkipUnknownFileTypes() throws IOException {
VirtualFile dir = getVirtualFile(createTempDirectory());
PsiTestUtil.addSourceContentToRoots(myModule, dir);
final VirtualFile vFile = createChildData(dir, "Foo.test");
VfsUtil.saveText(vFile, "Foo");
assertEquals(PlainTextFileType.INSTANCE, vFile.getFileType());
assertOneElement(PsiSearchHelper.SERVICE.getInstance(myProject).findFilesWithPlainTextWords("Foo"));
final Document document = FileDocumentManager.getInstance().getDocument(vFile);
//todo should file type be changed silently without events?
//assertEquals(UnknownFileType.INSTANCE, vFile.getFileType());
final PsiFile file = getPsiFile(document);
assertInstanceOf(file, PsiPlainTextFile.class);
assertEquals("Foo", file.getText());
assertOneElement(PsiSearchHelper.SERVICE.getInstance(myProject).findFilesWithPlainTextWords("Foo"));
WriteCommandAction.runWriteCommandAction(myProject, new Runnable() {
@Override
public void run() {
document.insertString(0, " ");
assertEquals("Foo", file.getText());
assertOneElement(PsiSearchHelper.SERVICE.getInstance(myProject).findFilesWithPlainTextWords("Foo"));
FileDocumentManager.getInstance().saveDocument(document);
assertEquals("Foo", file.getText());
assertOneElement(PsiSearchHelper.SERVICE.getInstance(myProject).findFilesWithPlainTextWords("Foo"));
PsiDocumentManager.getInstance(myProject).commitAllDocuments();
assertEquals(" Foo", file.getText());
assertOneElement(PsiSearchHelper.SERVICE.getInstance(myProject).findFilesWithPlainTextWords("Foo"));
}
});
}
}