mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
Patch for Bogdan Gheorghe:
- The initial framework for the new indexer. - Added a checkbox to the Indexer tab on the C/C++ Projects settings dialog to turn on the indexing on a per project basis.
This commit is contained in:
parent
728848ffc6
commit
afbe575516
70 changed files with 11247 additions and 140 deletions
|
@ -6,6 +6,7 @@
|
||||||
<classpathentry kind="src" path="parser/"/>
|
<classpathentry kind="src" path="parser/"/>
|
||||||
<classpathentry kind="src" path="resources/"/>
|
<classpathentry kind="src" path="resources/"/>
|
||||||
<classpathentry kind="src" path="suite/"/>
|
<classpathentry kind="src" path="suite/"/>
|
||||||
|
<classpathentry kind="src" path="indexer"/>
|
||||||
<classpathentry kind="src" path="/org.apache.xerces"/>
|
<classpathentry kind="src" path="/org.apache.xerces"/>
|
||||||
<classpathentry kind="src" path="/org.eclipse.core.resources"/>
|
<classpathentry kind="src" path="/org.eclipse.core.resources"/>
|
||||||
<classpathentry kind="src" path="/org.eclipse.core.runtime"/>
|
<classpathentry kind="src" path="/org.eclipse.core.runtime"/>
|
||||||
|
|
|
@ -0,0 +1,175 @@
|
||||||
|
/**********************************************************************
|
||||||
|
* Copyright (c) 2002,2003 Rational Software Corporation and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Common Public License v0.5
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/cpl-v05.html
|
||||||
|
***********************************************************************/
|
||||||
|
/*
|
||||||
|
* Created on Jun 19, 2003
|
||||||
|
*/
|
||||||
|
package org.eclipse.cdt.core.indexer.tests;
|
||||||
|
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.core.CCorePlugin;
|
||||||
|
import org.eclipse.cdt.core.CProjectNature;
|
||||||
|
import org.eclipse.cdt.internal.core.index.IEntryResult;
|
||||||
|
import org.eclipse.cdt.internal.core.index.IIndex;
|
||||||
|
import org.eclipse.cdt.internal.core.index.IQueryResult;
|
||||||
|
import org.eclipse.cdt.internal.core.index.impl.IFileDocument;
|
||||||
|
import org.eclipse.cdt.internal.core.search.indexing.IndexManager;
|
||||||
|
import org.eclipse.core.resources.IFile;
|
||||||
|
import org.eclipse.core.resources.IProject;
|
||||||
|
import org.eclipse.core.resources.IProjectDescription;
|
||||||
|
import org.eclipse.core.resources.IResource;
|
||||||
|
import org.eclipse.core.resources.IWorkspace;
|
||||||
|
import org.eclipse.core.resources.IWorkspaceRoot;
|
||||||
|
import org.eclipse.core.resources.ResourcesPlugin;
|
||||||
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
import org.eclipse.core.runtime.IPath;
|
||||||
|
import org.eclipse.core.runtime.IProgressMonitor;
|
||||||
|
import org.eclipse.core.runtime.NullProgressMonitor;
|
||||||
|
import org.eclipse.core.runtime.Path;
|
||||||
|
import org.eclipse.core.runtime.Platform;
|
||||||
|
|
||||||
|
import junit.framework.Test;
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
import junit.framework.TestSuite;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author bgheorgh
|
||||||
|
*/
|
||||||
|
public class IndexManagerTest extends TestCase {
|
||||||
|
IFile file;
|
||||||
|
IFileDocument fileDoc;
|
||||||
|
IProject testProject;
|
||||||
|
NullProgressMonitor monitor;
|
||||||
|
IndexManager indexManager;
|
||||||
|
/**
|
||||||
|
* Constructor for IndexManagerTest.
|
||||||
|
* @param name
|
||||||
|
*/
|
||||||
|
public IndexManagerTest(String name) {
|
||||||
|
super(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* @see TestCase#setUp()
|
||||||
|
*/
|
||||||
|
protected void setUp() throws Exception {
|
||||||
|
super.setUp();
|
||||||
|
//Create temp project
|
||||||
|
testProject = createProject("IndexerTestProject");
|
||||||
|
if (testProject==null)
|
||||||
|
fail("Unable to create project");
|
||||||
|
//Add a file to the project
|
||||||
|
importFile("mail.cpp","resources/indexer/mail.cpp");
|
||||||
|
//Start up the index manager
|
||||||
|
//indexManager = new IndexManager();
|
||||||
|
//indexManager.reset();
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* @see TestCase#tearDown()
|
||||||
|
*/
|
||||||
|
protected void tearDown() throws Exception {
|
||||||
|
super.tearDown();
|
||||||
|
//Delete project
|
||||||
|
//testProject.delete(true,monitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Test suite() {
|
||||||
|
return new TestSuite(IndexManagerTest.class);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Utils
|
||||||
|
*/
|
||||||
|
private IProject createProject(String projectName) throws CoreException
|
||||||
|
{
|
||||||
|
IWorkspaceRoot root= ResourcesPlugin.getWorkspace().getRoot();
|
||||||
|
IProject project= root.getProject(projectName);
|
||||||
|
if (!project.exists()) {
|
||||||
|
project.create(null);
|
||||||
|
} else {
|
||||||
|
project.refreshLocal(IResource.DEPTH_INFINITE, null);
|
||||||
|
}
|
||||||
|
if (!project.isOpen()) {
|
||||||
|
project.open(null);
|
||||||
|
}
|
||||||
|
if (!project.hasNature(CProjectNature.C_NATURE_ID)) {
|
||||||
|
addNatureToProject(project, CProjectNature.C_NATURE_ID, null);
|
||||||
|
}
|
||||||
|
//Fill out a project description
|
||||||
|
IPath defaultPath = Platform.getLocation();
|
||||||
|
IPath newPath = project.getFullPath();
|
||||||
|
if (defaultPath.equals(newPath))
|
||||||
|
newPath = null;
|
||||||
|
IWorkspace workspace = ResourcesPlugin.getWorkspace();
|
||||||
|
IProjectDescription description = workspace.newProjectDescription(project.getName());
|
||||||
|
description.setLocation(newPath);
|
||||||
|
//Create the project
|
||||||
|
IProject cproject = CCorePlugin.getDefault().createCProject(description,project,monitor,CCorePlugin.PLUGIN_ID + ".make"); //.getCoreModel().create(project);
|
||||||
|
|
||||||
|
return cproject;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void importFile(String fileName, String resourceLocation)throws Exception{
|
||||||
|
//Obtain file handle
|
||||||
|
file = testProject.getProject().getFile(fileName);
|
||||||
|
String pluginRoot=org.eclipse.core.runtime.Platform.getPlugin("org.eclipse.cdt.core.tests").find(new Path("/")).getFile();
|
||||||
|
//Create file input stream
|
||||||
|
monitor = new NullProgressMonitor();
|
||||||
|
if (!file.exists()){
|
||||||
|
file.create(new FileInputStream(pluginRoot + resourceLocation),false,monitor);
|
||||||
|
}
|
||||||
|
fileDoc = new IFileDocument(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addNatureToProject(IProject proj, String natureId, IProgressMonitor monitor) throws CoreException {
|
||||||
|
IProjectDescription description = proj.getDescription();
|
||||||
|
String[] prevNatures= description.getNatureIds();
|
||||||
|
String[] newNatures= new String[prevNatures.length + 1];
|
||||||
|
System.arraycopy(prevNatures, 0, newNatures, 0, prevNatures.length);
|
||||||
|
newNatures[prevNatures.length]= natureId;
|
||||||
|
description.setNatureIds(newNatures);
|
||||||
|
proj.setDescription(description, monitor);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Start of tests
|
||||||
|
*/
|
||||||
|
public void testIndexAll() throws Exception {
|
||||||
|
//Enable indexing on the created project
|
||||||
|
//By doing this, we force the Index Manager to indexAll()
|
||||||
|
indexManager = CCorePlugin.getDefault().getCoreModel().getIndexManager();
|
||||||
|
indexManager.setEnabled(testProject,true);
|
||||||
|
|
||||||
|
Thread.sleep(15000);
|
||||||
|
IIndex ind = indexManager.getIndex(testProject.getFullPath(),true,true);
|
||||||
|
char[] prefix = "typeDecl/".toCharArray();
|
||||||
|
IQueryResult[] qresults = ind.queryPrefix(prefix);
|
||||||
|
IEntryResult[] eresults = ind.queryEntries(prefix);
|
||||||
|
String [] queryResultModel = {"IndexedFile(1: /IndexerTestProject/mail.cpp)"};
|
||||||
|
String [] entryResultModel ={"EntryResult: word=typeDecl/C/Mail/, refs={ 1 }", "EntryResult: word=typeDecl/C/Unknown/, refs={ 1 }", "EntryResult: word=typeDecl/C/container/, refs={ 1 }", "EntryResult: word=typeDecl/C/first_class/, refs={ 1 }", "EntryResult: word=typeDecl/C/postcard/, refs={ 1 }"};
|
||||||
|
|
||||||
|
if (qresults.length != queryResultModel.length)
|
||||||
|
fail("Query Result length different from model");
|
||||||
|
|
||||||
|
if (eresults.length != entryResultModel.length)
|
||||||
|
fail("Entry Result length different from model");
|
||||||
|
|
||||||
|
|
||||||
|
for (int i=0; i<qresults.length;i++)
|
||||||
|
{
|
||||||
|
assertEquals(queryResultModel[i],qresults[i].toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i=0;i<eresults.length; i++)
|
||||||
|
{
|
||||||
|
assertEquals(entryResultModel[i],eresults[i].toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
98
core/org.eclipse.cdt.core.tests/resources/indexer/mail.cpp
Normal file
98
core/org.eclipse.cdt.core.tests/resources/indexer/mail.cpp
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
#include <iostream.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <alloc.h>
|
||||||
|
#include <iomanip.h>
|
||||||
|
|
||||||
|
class Mail
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Mail(){}
|
||||||
|
virtual void print()=0; //Pure Virtual Function, forces redefinition
|
||||||
|
protected:
|
||||||
|
float postage;
|
||||||
|
char *type;
|
||||||
|
friend ostream& operator << (ostream& os, Mail *m);
|
||||||
|
};
|
||||||
|
|
||||||
|
class postcard : public Mail
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
postcard(): Mail(){postage = 0.20; type = "Postcard";}
|
||||||
|
void print(){cout << type << ": $" << setiosflags(ios::fixed)
|
||||||
|
<<setprecision(2) << postage <<endl;}
|
||||||
|
};
|
||||||
|
|
||||||
|
class first_class : public Mail
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
first_class() : Mail(){postage = 0.32; type = "First Class";}
|
||||||
|
void print(){cout << type << ": $" <<setiosflags(ios::fixed)
|
||||||
|
<< setprecision(2) << postage <<endl;}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class Unknown : public postcard, first_class // ??? Multiple Inheritance
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Unknown(): postcard(), first_class()
|
||||||
|
{
|
||||||
|
postcard::postage = 1.50; // MUST disambiguate
|
||||||
|
postcard::type = "Unknown";
|
||||||
|
}
|
||||||
|
void print(){cout << postcard::type << ": $" <<setiosflags(ios::fixed)
|
||||||
|
<<setprecision(2)<<postcard::postage <<endl;}
|
||||||
|
};
|
||||||
|
|
||||||
|
class container
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
Mail **array;
|
||||||
|
int index;
|
||||||
|
int sz;
|
||||||
|
public:
|
||||||
|
container(){array = 0;}
|
||||||
|
~container(){
|
||||||
|
for(int x = 0; x <sz; x++)
|
||||||
|
delete array[x];
|
||||||
|
free(array);
|
||||||
|
}
|
||||||
|
int size() {return sz;}
|
||||||
|
Mail* operator[](int index);
|
||||||
|
Mail* operator = (Mail* mail);
|
||||||
|
};
|
||||||
|
|
||||||
|
main()
|
||||||
|
{
|
||||||
|
container PO_Box;
|
||||||
|
PO_Box = new postcard;
|
||||||
|
PO_Box = new first_class;
|
||||||
|
PO_Box = new parcel_Post;
|
||||||
|
//PO_Box = new Unknown;
|
||||||
|
//one way of printing information
|
||||||
|
for(int x =0; x <3; x++){
|
||||||
|
PO_Box[x]->print();
|
||||||
|
}
|
||||||
|
//Overloaded <<
|
||||||
|
for(int x =0; x <PO_Box.size(); x++){
|
||||||
|
cout << PO_Box[x];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ostream& operator << (ostream &os, Mail *m)
|
||||||
|
{
|
||||||
|
os <<setiosflags(ios::fixed) << setprecision(2)<< m->type
|
||||||
|
<< ": $" << m->postage <<endl;
|
||||||
|
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
Mail* container::operator[](int index) {return array[index];}
|
||||||
|
Mail* container::operator = (Mail* mail)
|
||||||
|
{
|
||||||
|
int size = sizeof(Mail*) * (++sz);
|
||||||
|
int temp = sz -1;
|
||||||
|
array = (Mail**)realloc(array, size);
|
||||||
|
array[temp] = mail;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,17 @@
|
||||||
Added new constant for comma-separated lists
|
Added new constant for comma-separated lists
|
||||||
* src/org/eclipse/cdt/core/resources/IBuildInfo.java
|
* src/org/eclipse/cdt/core/resources/IBuildInfo.java
|
||||||
|
|
||||||
|
2003-06-25 Bogdan Gheorghe
|
||||||
|
|
||||||
|
* src/org/eclipse/cdt/core/CCorePlugin.java
|
||||||
|
Start the new indexer thread on startup
|
||||||
|
* src/org/eclipse/cdt/core/model/CoreModel.java
|
||||||
|
Added some methods to access the IndexManager
|
||||||
|
* src/org/eclipse/cdt/internal/core/model/CModelManager.java
|
||||||
|
Added some methods to access the IndexManager
|
||||||
|
* src/org/eclipse/cdt/internal/core/model/DeltaProcessor.java
|
||||||
|
Added IndexManager member
|
||||||
|
|
||||||
2003-06-24 Alain Magloire
|
2003-06-24 Alain Magloire
|
||||||
|
|
||||||
Patch form ando@park.ruru.ne.jp, to deal
|
Patch form ando@park.ruru.ne.jp, to deal
|
||||||
|
|
60
core/org.eclipse.cdt.core/index/ChangeLog
Normal file
60
core/org.eclipse.cdt.core/index/ChangeLog
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
2003-06-25 Bogdan Gheorghe
|
||||||
|
|
||||||
|
Added new Indexer framework:
|
||||||
|
|
||||||
|
* index/org/eclipse/cdt/internal/core/index/IDocument.java
|
||||||
|
* index/org/eclipse/cdt/internal/core/index/IEntryResult.java
|
||||||
|
* index/org/eclipse/cdt/internal/core/index/IIndex.java
|
||||||
|
* index/org/eclipse/cdt/internal/core/index/IIndexer.java
|
||||||
|
* index/org/eclipse/cdt/internal/core/index/IIndexerOutput.java
|
||||||
|
* index/org/eclipse/cdt/internal/core/index/IQueryResult.java
|
||||||
|
|
||||||
|
* index/org/eclipse/cdt/internal/core/index/impl/Block.java
|
||||||
|
* index/org/eclipse/cdt/internal/core/index/impl/BlocksIndexInput.java
|
||||||
|
* index/org/eclipse/cdt/internal/core/index/impl/BlocksIndexOutput.java
|
||||||
|
* index/org/eclipse/cdt/internal/core/index/impl/CodeByteStream.java
|
||||||
|
* index/org/eclipse/cdt/internal/core/index/impl/EntryResult.java
|
||||||
|
* index/org/eclipse/cdt/internal/core/index/impl/Field.java
|
||||||
|
* index/org/eclipse/cdt/internal/core/index/impl/GammaCompressedIndexBlock.java
|
||||||
|
* index/org/eclipse/cdt/internal/core/index/impl/IFileDocument.java
|
||||||
|
* index/org/eclipse/cdt/internal/core/index/impl/IIndexConstants.java
|
||||||
|
* index/org/eclipse/cdt/internal/core/index/impl/Index.java
|
||||||
|
* index/org/eclipse/cdt/internal/core/index/impl/IndexBlock.java
|
||||||
|
* index/org/eclipse/cdt/internal/core/index/impl/IndexedFile.java
|
||||||
|
* index/org/eclipse/cdt/internal/core/index/impl/IndexedFileHashedArray.java
|
||||||
|
* index/org/eclipse/cdt/internal/core/index/impl/IndexerOutput.java
|
||||||
|
* index/org/eclipse/cdt/internal/core/index/impl/IndexInput.java
|
||||||
|
* index/org/eclipse/cdt/internal/core/index/impl/IndexOutput.java
|
||||||
|
* index/org/eclipse/cdt/internal/core/index/impl/IndexSummary.java
|
||||||
|
* index/org/eclipse/cdt/internal/core/index/impl/InMemoryIndex.java
|
||||||
|
* index/org/eclipse/cdt/internal/core/index/impl/Int.java
|
||||||
|
* index/org/eclipse/cdt/internal/core/index/impl/MergeFactory.java
|
||||||
|
* index/org/eclipse/cdt/internal/core/index/impl/PropertyDocument.java
|
||||||
|
* index/org/eclipse/cdt/internal/core/index/impl/SafeRandomAccessFile.java
|
||||||
|
* index/org/eclipse/cdt/internal/core/index/impl/SimpleIndexInput.java
|
||||||
|
* index/org/eclipse/cdt/internal/core/index/impl/Util.java
|
||||||
|
* index/org/eclipse/cdt/internal/core/index/impl/WordEntry.java
|
||||||
|
* index/org/eclipse/cdt/internal/core/index/impl/WordEntryHashedArray.java
|
||||||
|
|
||||||
|
* index/org/eclipse/cdt/internal/core/search/CharOperation.java
|
||||||
|
* index/org/eclipse/cdt/internal/core/search/HashtableOfInt.java
|
||||||
|
* index/org/eclipse/cdt/internal/core/search/SimpleLookupTable.java
|
||||||
|
* index/org/eclipse/cdt/internal/core/search/Util.java
|
||||||
|
* index/org/eclipse/cdt/internal/core/search/message.properties
|
||||||
|
|
||||||
|
* index/org/eclipse/cdt/internal/core/search/indexing/AbstractIndexer.java
|
||||||
|
* index/org/eclipse/cdt/internal/core/search/indexing/AddCompilationUnitToIndex.java
|
||||||
|
* index/org/eclipse/cdt/internal/core/search/indexing/AddFileToIndex.java
|
||||||
|
* index/org/eclipse/cdt/internal/core/search/indexing/AddFolderToIndex.java
|
||||||
|
* index/org/eclipse/cdt/internal/core/search/indexing/IIndexConstants.java
|
||||||
|
* index/org/eclipse/cdt/internal/core/search/indexing/IndexAllProject.java
|
||||||
|
* index/org/eclipse/cdt/internal/core/search/indexing/IndexManager.java
|
||||||
|
* index/org/eclipse/cdt/internal/core/search/indexing/IndexRequest.java
|
||||||
|
* index/org/eclipse/cdt/internal/core/search/indexing/ReadWriteMonitor.java
|
||||||
|
* index/org/eclipse/cdt/internal/core/search/indexing/RemoveFolderFromIndex.java
|
||||||
|
* index/org/eclipse/cdt/internal/core/search/indexing/RemoveFromIndex.java
|
||||||
|
* index/org/eclipse/cdt/internal/core/search/indexing/SaveIndex.java
|
||||||
|
* index/org/eclipse/cdt/internal/core/search/indexing/SourceIndexer.java
|
||||||
|
* index/org/eclipse/cdt/internal/core/search/indexing/SourceIndexerRequestor.java
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2003 IBM Corporation and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Common Public License v0.5
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/cpl-v05.html
|
||||||
|
******************************************************************************/
|
||||||
|
/*
|
||||||
|
* Created on May 30, 2003
|
||||||
|
*/
|
||||||
|
package org.eclipse.cdt.internal.core.index;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An <code>IDocument</code> represent a data source, e.g. a <code>File</code> (<code>FileDocument</code>),
|
||||||
|
* an <code>IFile</code> (<code>IFileDocument</code>),
|
||||||
|
* or other kinds of data sources (URL, ...). An <code>IIndexer</code> indexes an<code>IDocument</code>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public interface IDocument {
|
||||||
|
/**
|
||||||
|
* Returns the content of the document, in a byte array.
|
||||||
|
*/
|
||||||
|
byte[] getByteContent() throws IOException;
|
||||||
|
/**
|
||||||
|
* Returns the content of the document, in a char array.
|
||||||
|
*/
|
||||||
|
char[] getCharContent() throws IOException;
|
||||||
|
/**
|
||||||
|
* Returns the encoding for this document
|
||||||
|
*/
|
||||||
|
String getEncoding();
|
||||||
|
/**
|
||||||
|
* returns the name of the document (e.g. its path for a <code>File</code>, or its relative path
|
||||||
|
* in the workbench for an <code>IFile</code>).
|
||||||
|
*/
|
||||||
|
String getName();
|
||||||
|
/**
|
||||||
|
* Returns the content of the document, as a String.
|
||||||
|
*/
|
||||||
|
public String getStringContent() throws IOException;
|
||||||
|
/**
|
||||||
|
* Returns the type of the document.
|
||||||
|
*/
|
||||||
|
String getType();
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2003 IBM Corporation and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Common Public License v0.5
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/cpl-v05.html
|
||||||
|
******************************************************************************/
|
||||||
|
/*
|
||||||
|
* Created on May 30, 2003
|
||||||
|
*/
|
||||||
|
package org.eclipse.cdt.internal.core.index;
|
||||||
|
|
||||||
|
public interface IEntryResult {
|
||||||
|
public int[] getFileReferences();
|
||||||
|
public char[] getWord();
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,75 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2003 IBM Corporation and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Common Public License v0.5
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/cpl-v05.html
|
||||||
|
******************************************************************************/
|
||||||
|
/*
|
||||||
|
* Created on May 30, 2003
|
||||||
|
*/
|
||||||
|
package org.eclipse.cdt.internal.core.index;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An IIndex is the interface used to generate an index file, and to make queries on
|
||||||
|
* this index.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public interface IIndex {
|
||||||
|
/**
|
||||||
|
* Adds the given document to the index.
|
||||||
|
*/
|
||||||
|
void add(IDocument document, IIndexer indexer) throws IOException;
|
||||||
|
/**
|
||||||
|
* Empties the index.
|
||||||
|
*/
|
||||||
|
void empty() throws IOException;
|
||||||
|
/**
|
||||||
|
* Returns the index file on the disk.
|
||||||
|
*/
|
||||||
|
File getIndexFile();
|
||||||
|
/**
|
||||||
|
* Returns the number of documents indexed.
|
||||||
|
*/
|
||||||
|
int getNumDocuments() throws IOException;
|
||||||
|
/**
|
||||||
|
* Returns the number of unique words indexed.
|
||||||
|
*/
|
||||||
|
int getNumWords() throws IOException;
|
||||||
|
/**
|
||||||
|
* Returns the path corresponding to a given document number
|
||||||
|
*/
|
||||||
|
String getPath(int documentNumber) throws IOException;
|
||||||
|
/**
|
||||||
|
* Ansers true if has some changes to save.
|
||||||
|
*/
|
||||||
|
boolean hasChanged();
|
||||||
|
/**
|
||||||
|
* Returns the paths of the documents containing the given word.
|
||||||
|
*/
|
||||||
|
IQueryResult[] query(String word) throws IOException;
|
||||||
|
/**
|
||||||
|
* Returns all entries for a given word.
|
||||||
|
*/
|
||||||
|
IEntryResult[] queryEntries(char[] pattern) throws IOException;
|
||||||
|
/**
|
||||||
|
* Returns the paths of the documents whose names contain the given word.
|
||||||
|
*/
|
||||||
|
IQueryResult[] queryInDocumentNames(String word) throws IOException;
|
||||||
|
/**
|
||||||
|
* Returns the paths of the documents containing the given word prefix.
|
||||||
|
*/
|
||||||
|
IQueryResult[] queryPrefix(char[] prefix) throws IOException;
|
||||||
|
/**
|
||||||
|
* Removes the corresponding document from the index.
|
||||||
|
*/
|
||||||
|
void remove(String documentName) throws IOException;
|
||||||
|
/**
|
||||||
|
* Saves the index on the disk.
|
||||||
|
*/
|
||||||
|
void save() throws IOException;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2003 IBM Corporation and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Common Public License v0.5
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/cpl-v05.html
|
||||||
|
******************************************************************************/
|
||||||
|
/*
|
||||||
|
* Created on May 30, 2003
|
||||||
|
*/
|
||||||
|
package org.eclipse.cdt.internal.core.index;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An <code>IIndexer</code> indexes ONE document at each time. It adds the document names and
|
||||||
|
* the words references to an IIndex. Each IIndexer can index certain types of document, and should
|
||||||
|
* not index the other files.
|
||||||
|
*/
|
||||||
|
public interface IIndexer {
|
||||||
|
/**
|
||||||
|
* Returns the file types the <code>IIndexer</code> handles.
|
||||||
|
*/
|
||||||
|
|
||||||
|
String[] getFileTypes();
|
||||||
|
/**
|
||||||
|
* Indexes the given document, adding the document name and the word references
|
||||||
|
* to this document to the given <code>IIndex</code>.The caller should use
|
||||||
|
* <code>shouldIndex()</code> first to determine whether this indexer handles
|
||||||
|
* the given type of file, and only call this method if so.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void index(IDocument document, IIndexerOutput output) throws java.io.IOException;
|
||||||
|
/**
|
||||||
|
* Sets the document types the <code>IIndexer</code> handles.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public void setFileTypes(String[] fileTypes);
|
||||||
|
/**
|
||||||
|
* Returns whether the <code>IIndexer</code> can index the given document or not.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public boolean shouldIndex(IDocument document);
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2003 IBM Corporation and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Common Public License v0.5
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/cpl-v05.html
|
||||||
|
******************************************************************************/
|
||||||
|
/*
|
||||||
|
* Created on May 30, 2003
|
||||||
|
*/
|
||||||
|
package org.eclipse.cdt.internal.core.index;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class represents the output from an indexer to an index
|
||||||
|
* for a single document.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public interface IIndexerOutput {
|
||||||
|
public void addDocument(IDocument document);
|
||||||
|
public void addRef(char[] word);
|
||||||
|
public void addRef(String word);
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2003 IBM Corporation and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Common Public License v0.5
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/cpl-v05.html
|
||||||
|
******************************************************************************/
|
||||||
|
/*
|
||||||
|
* Created on May 30, 2003
|
||||||
|
*/
|
||||||
|
package org.eclipse.cdt.internal.core.index;
|
||||||
|
|
||||||
|
public interface IQueryResult {
|
||||||
|
String getPath();
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2003 IBM Corporation and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Common Public License v0.5
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/cpl-v05.html
|
||||||
|
******************************************************************************/
|
||||||
|
/*
|
||||||
|
* Created on Jun 1, 2003
|
||||||
|
*/
|
||||||
|
package org.eclipse.cdt.internal.core.index.impl;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.RandomAccessFile;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A block is a container that can hold information (a list of file names, a list of
|
||||||
|
* words, ...), be saved on the disk and loaded in memory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public abstract class Block {
|
||||||
|
/**
|
||||||
|
* Size of the block
|
||||||
|
*/
|
||||||
|
protected int blockSize;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Field in which the information is stored
|
||||||
|
*/
|
||||||
|
protected Field field;
|
||||||
|
|
||||||
|
public Block(int blockSize) {
|
||||||
|
this.blockSize= blockSize;
|
||||||
|
field= new Field(blockSize);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Empties the block.
|
||||||
|
*/
|
||||||
|
public void clear() {
|
||||||
|
field.clear();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Flushes the block
|
||||||
|
*/
|
||||||
|
public void flush() {
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Loads the block with the given number in memory, reading it from a RandomAccessFile.
|
||||||
|
*/
|
||||||
|
public void read(RandomAccessFile raf, int blockNum) throws IOException {
|
||||||
|
raf.seek(blockNum * (long) blockSize);
|
||||||
|
raf.readFully(field.buffer());
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Writes the block in a RandomAccessFile, giving it a block number.
|
||||||
|
*/
|
||||||
|
public void write(RandomAccessFile raf, int blockNum) throws IOException {
|
||||||
|
raf.seek(blockNum * (long) blockSize);
|
||||||
|
raf.write(field.buffer());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,391 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2003 IBM Corporation and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Common Public License v0.5
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/cpl-v05.html
|
||||||
|
******************************************************************************/
|
||||||
|
/*
|
||||||
|
* Created on Jun 1, 2003
|
||||||
|
*/
|
||||||
|
package org.eclipse.cdt.internal.core.index.impl;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.RandomAccessFile;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.internal.core.search.CharOperation;
|
||||||
|
import org.eclipse.cdt.internal.core.index.IDocument;
|
||||||
|
import org.eclipse.cdt.internal.core.index.IEntryResult;
|
||||||
|
import org.eclipse.cdt.internal.core.index.IQueryResult;
|
||||||
|
import org.eclipse.cdt.internal.core.search.Util;
|
||||||
|
import org.eclipse.cdt.internal.core.util.LRUCache;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This input is used for reading indexes saved using a BlocksIndexOutput.
|
||||||
|
*/
|
||||||
|
public class BlocksIndexInput extends IndexInput {
|
||||||
|
public static final int CACHE_SIZE= 16; // Cache 16 blocks of 8K each, for a cache size of 128K
|
||||||
|
protected FileListBlock currentFileListBlock;
|
||||||
|
protected int currentFileListBlockNum;
|
||||||
|
protected int currentIndexBlockNum;
|
||||||
|
protected IndexBlock currentIndexBlock;
|
||||||
|
private RandomAccessFile raf;
|
||||||
|
protected File indexFile;
|
||||||
|
protected LRUCache blockCache;
|
||||||
|
protected boolean opened= false;
|
||||||
|
protected IndexSummary summary;
|
||||||
|
|
||||||
|
public BlocksIndexInput(File inputFile) {
|
||||||
|
this.indexFile= inputFile;
|
||||||
|
blockCache= new LRUCache(CACHE_SIZE);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @see IndexInput#clearCache()
|
||||||
|
*/
|
||||||
|
public void clearCache() {
|
||||||
|
blockCache= new LRUCache(CACHE_SIZE);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @see IndexInput#close()
|
||||||
|
*/
|
||||||
|
public void close() throws IOException {
|
||||||
|
if (opened) {
|
||||||
|
summary= null;
|
||||||
|
opened= false;
|
||||||
|
if (raf != null)
|
||||||
|
raf.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @see IndexInput#getCurrentFile()
|
||||||
|
*/
|
||||||
|
public IndexedFile getCurrentFile() throws IOException {
|
||||||
|
if (!hasMoreFiles())
|
||||||
|
return null;
|
||||||
|
IndexedFile file= null;
|
||||||
|
if ((file= currentFileListBlock.getFile(filePosition)) == null) {
|
||||||
|
currentFileListBlockNum= summary.getBlockNumForFileNum(filePosition);
|
||||||
|
currentFileListBlock= getFileListBlock(currentFileListBlockNum);
|
||||||
|
file= currentFileListBlock.getFile(filePosition);
|
||||||
|
}
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Returns the entry corresponding to the given word.
|
||||||
|
*/
|
||||||
|
protected WordEntry getEntry(char[] word) throws IOException {
|
||||||
|
int blockNum= summary.getBlockNumForWord(word);
|
||||||
|
if (blockNum == -1) return null;
|
||||||
|
IndexBlock block= getIndexBlock(blockNum);
|
||||||
|
return block.findExactEntry(word);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Returns the FileListBlock with the given number.
|
||||||
|
*/
|
||||||
|
protected FileListBlock getFileListBlock(int blockNum) throws IOException {
|
||||||
|
Integer key= new Integer(blockNum);
|
||||||
|
Block block= (Block) blockCache.get(key);
|
||||||
|
if (block != null && block instanceof FileListBlock)
|
||||||
|
return (FileListBlock) block;
|
||||||
|
FileListBlock fileListBlock= new FileListBlock(IIndexConstants.BLOCK_SIZE);
|
||||||
|
fileListBlock.read(raf, blockNum);
|
||||||
|
blockCache.put(key, fileListBlock);
|
||||||
|
return fileListBlock;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Returns the IndexBlock (containing words) with the given number.
|
||||||
|
*/
|
||||||
|
protected IndexBlock getIndexBlock(int blockNum) throws IOException {
|
||||||
|
Integer key= new Integer(blockNum);
|
||||||
|
Block block= (Block) blockCache.get(key);
|
||||||
|
if (block != null && block instanceof IndexBlock)
|
||||||
|
return (IndexBlock) block;
|
||||||
|
IndexBlock indexBlock= new GammaCompressedIndexBlock(IIndexConstants.BLOCK_SIZE);
|
||||||
|
indexBlock.read(raf, blockNum);
|
||||||
|
blockCache.put(key, indexBlock);
|
||||||
|
return indexBlock;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @see IndexInput#getIndexedFile(int)
|
||||||
|
*/
|
||||||
|
public IndexedFile getIndexedFile(int fileNum) throws IOException {
|
||||||
|
int blockNum= summary.getBlockNumForFileNum(fileNum);
|
||||||
|
if (blockNum == -1)
|
||||||
|
return null;
|
||||||
|
FileListBlock block= getFileListBlock(blockNum);
|
||||||
|
return block.getFile(fileNum);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @see IndexInput#getIndexedFile(IDocument)
|
||||||
|
*/
|
||||||
|
public IndexedFile getIndexedFile(IDocument document) throws java.io.IOException {
|
||||||
|
setFirstFile();
|
||||||
|
String name= document.getName();
|
||||||
|
while (hasMoreFiles()) {
|
||||||
|
IndexedFile file= getCurrentFile();
|
||||||
|
String path= file.getPath();
|
||||||
|
if (path.equals(name))
|
||||||
|
return file;
|
||||||
|
moveToNextFile();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Returns the list of numbers of files containing the given word.
|
||||||
|
*/
|
||||||
|
|
||||||
|
protected int[] getMatchingFileNumbers(char[] word) throws IOException {
|
||||||
|
int blockNum= summary.getBlockNumForWord(word);
|
||||||
|
if (blockNum == -1)
|
||||||
|
return new int[0];
|
||||||
|
IndexBlock block= getIndexBlock(blockNum);
|
||||||
|
WordEntry entry= block.findExactEntry(word);
|
||||||
|
return entry == null ? new int[0] : entry.getRefs();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @see IndexInput#getNumFiles()
|
||||||
|
*/
|
||||||
|
public int getNumFiles() {
|
||||||
|
return summary.getNumFiles();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @see IndexInput#getNumWords()
|
||||||
|
*/
|
||||||
|
public int getNumWords() {
|
||||||
|
return summary.getNumWords();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @see IndexInput#getSource()
|
||||||
|
*/
|
||||||
|
public Object getSource() {
|
||||||
|
return indexFile;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Initialises the blocksIndexInput
|
||||||
|
*/
|
||||||
|
protected void init() throws IOException {
|
||||||
|
clearCache();
|
||||||
|
setFirstFile();
|
||||||
|
setFirstWord();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @see IndexInput#moveToNextFile()
|
||||||
|
*/
|
||||||
|
public void moveToNextFile() throws IOException {
|
||||||
|
filePosition++;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @see IndexInput#moveToNextWordEntry()
|
||||||
|
*/
|
||||||
|
public void moveToNextWordEntry() throws IOException {
|
||||||
|
wordPosition++;
|
||||||
|
if (!hasMoreWords()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//if end of the current block, we load the next one.
|
||||||
|
boolean endOfBlock= !currentIndexBlock.nextEntry(currentWordEntry);
|
||||||
|
if (endOfBlock) {
|
||||||
|
currentIndexBlock= getIndexBlock(++currentIndexBlockNum);
|
||||||
|
currentIndexBlock.nextEntry(currentWordEntry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @see IndexInput#open()
|
||||||
|
*/
|
||||||
|
|
||||||
|
public void open() throws IOException {
|
||||||
|
if (!opened) {
|
||||||
|
raf= new SafeRandomAccessFile(indexFile, "r"); //$NON-NLS-1$
|
||||||
|
String sig= raf.readUTF();
|
||||||
|
if (!sig.equals(IIndexConstants.SIGNATURE))
|
||||||
|
throw new IOException(Util.bind("exception.wrongFormat")); //$NON-NLS-1$
|
||||||
|
int summaryBlockNum= raf.readInt();
|
||||||
|
raf.seek(summaryBlockNum * (long) IIndexConstants.BLOCK_SIZE);
|
||||||
|
summary= new IndexSummary();
|
||||||
|
summary.read(raf);
|
||||||
|
init();
|
||||||
|
opened= true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @see IndexInput#query(String)
|
||||||
|
*/
|
||||||
|
public IQueryResult[] query(String word) throws IOException {
|
||||||
|
open();
|
||||||
|
int[] fileNums= getMatchingFileNumbers(word.toCharArray());
|
||||||
|
int size= fileNums.length;
|
||||||
|
IQueryResult[] files= new IQueryResult[size];
|
||||||
|
for (int i= 0; i < size; ++i) {
|
||||||
|
files[i]= getIndexedFile(fileNums[i]);
|
||||||
|
}
|
||||||
|
return files;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* If no prefix is provided in the pattern, then this operation will have to walk
|
||||||
|
* all the entries of the whole index.
|
||||||
|
*/
|
||||||
|
public IEntryResult[] queryEntriesMatching(char[] pattern/*, boolean isCaseSensitive*/) throws IOException {
|
||||||
|
open();
|
||||||
|
|
||||||
|
if (pattern == null || pattern.length == 0) return null;
|
||||||
|
int[] blockNums = null;
|
||||||
|
int firstStar = CharOperation.indexOf('*', pattern);
|
||||||
|
switch (firstStar){
|
||||||
|
case -1 :
|
||||||
|
WordEntry entry = getEntry(pattern);
|
||||||
|
if (entry == null) return null;
|
||||||
|
return new IEntryResult[]{ new EntryResult(entry.getWord(), entry.getRefs()) };
|
||||||
|
case 0 :
|
||||||
|
blockNums = summary.getAllBlockNums();
|
||||||
|
break;
|
||||||
|
default :
|
||||||
|
char[] prefix = CharOperation.subarray(pattern, 0, firstStar);
|
||||||
|
blockNums = summary.getBlockNumsForPrefix(prefix);
|
||||||
|
}
|
||||||
|
if (blockNums == null || blockNums.length == 0) return null;
|
||||||
|
|
||||||
|
IEntryResult[] entries = new IEntryResult[5];
|
||||||
|
int count = 0;
|
||||||
|
for (int i = 0, max = blockNums.length; i < max; i++) {
|
||||||
|
IndexBlock block = getIndexBlock(blockNums[i]);
|
||||||
|
block.reset();
|
||||||
|
boolean found = false;
|
||||||
|
WordEntry entry = new WordEntry();
|
||||||
|
while (block.nextEntry(entry)) {
|
||||||
|
if (CharOperation.match(entry.getWord(), pattern, true)) {
|
||||||
|
if (count == entries.length){
|
||||||
|
System.arraycopy(entries, 0, entries = new IEntryResult[count*2], 0, count);
|
||||||
|
}
|
||||||
|
entries[count++] = new EntryResult(entry.getWord(), entry.getRefs());
|
||||||
|
found = true;
|
||||||
|
} else {
|
||||||
|
if (found) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (count != entries.length){
|
||||||
|
System.arraycopy(entries, 0, entries = new IEntryResult[count], 0, count);
|
||||||
|
}
|
||||||
|
return entries;
|
||||||
|
}
|
||||||
|
public IEntryResult[] queryEntriesPrefixedBy(char[] prefix) throws IOException {
|
||||||
|
open();
|
||||||
|
|
||||||
|
int blockLoc = summary.getFirstBlockLocationForPrefix(prefix);
|
||||||
|
if (blockLoc < 0) return null;
|
||||||
|
|
||||||
|
IEntryResult[] entries = new IEntryResult[5];
|
||||||
|
int count = 0;
|
||||||
|
while(blockLoc >= 0){
|
||||||
|
IndexBlock block = getIndexBlock(summary.getBlockNum(blockLoc));
|
||||||
|
block.reset();
|
||||||
|
boolean found = false;
|
||||||
|
WordEntry entry = new WordEntry();
|
||||||
|
while (block.nextEntry(entry)) {
|
||||||
|
if (CharOperation.prefixEquals(prefix, entry.getWord())) {
|
||||||
|
if (count == entries.length){
|
||||||
|
System.arraycopy(entries, 0, entries = new IEntryResult[count*2], 0, count);
|
||||||
|
}
|
||||||
|
entries[count++] = new EntryResult(entry.getWord(), entry.getRefs());
|
||||||
|
found = true;
|
||||||
|
} else {
|
||||||
|
if (found) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* consider next block ? */
|
||||||
|
blockLoc = summary.getNextBlockLocationForPrefix(prefix, blockLoc);
|
||||||
|
}
|
||||||
|
if (count == 0) return null;
|
||||||
|
if (count != entries.length){
|
||||||
|
System.arraycopy(entries, 0, entries = new IEntryResult[count], 0, count);
|
||||||
|
}
|
||||||
|
return entries;
|
||||||
|
}
|
||||||
|
public IQueryResult[] queryFilesReferringToPrefix(char[] prefix) throws IOException {
|
||||||
|
open();
|
||||||
|
|
||||||
|
int blockLoc = summary.getFirstBlockLocationForPrefix(prefix);
|
||||||
|
if (blockLoc < 0) return null;
|
||||||
|
|
||||||
|
// each filename must be returned already once
|
||||||
|
org.eclipse.cdt.internal.core.search.HashtableOfInt fileMatches = new org.eclipse.cdt.internal.core.search.HashtableOfInt(20);
|
||||||
|
int count = 0;
|
||||||
|
while(blockLoc >= 0){
|
||||||
|
IndexBlock block = getIndexBlock(summary.getBlockNum(blockLoc));
|
||||||
|
block.reset();
|
||||||
|
boolean found = false;
|
||||||
|
WordEntry entry = new WordEntry();
|
||||||
|
while (block.nextEntry(entry)) {
|
||||||
|
if (CharOperation.prefixEquals(prefix, entry.getWord()/*, isCaseSensitive*/)) {
|
||||||
|
int [] refs = entry.getRefs();
|
||||||
|
for (int i = 0, max = refs.length; i < max; i++){
|
||||||
|
int ref = refs[i];
|
||||||
|
if (!fileMatches.containsKey(ref)){
|
||||||
|
count++;
|
||||||
|
fileMatches.put(ref, getIndexedFile(ref));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
found = true;
|
||||||
|
} else {
|
||||||
|
if (found) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* consider next block ? */
|
||||||
|
blockLoc = summary.getNextBlockLocationForPrefix(prefix, blockLoc);
|
||||||
|
}
|
||||||
|
/* extract indexed files */
|
||||||
|
IQueryResult[] files = new IQueryResult[count];
|
||||||
|
Object[] indexedFiles = fileMatches.valueTable;
|
||||||
|
for (int i = 0, index = 0, max = indexedFiles.length; i < max; i++){
|
||||||
|
IndexedFile indexedFile = (IndexedFile) indexedFiles[i];
|
||||||
|
if (indexedFile != null){
|
||||||
|
files[index++] = indexedFile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return files;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @see IndexInput#queryInDocumentNames(String)
|
||||||
|
*/
|
||||||
|
public IQueryResult[] queryInDocumentNames(String word) throws IOException {
|
||||||
|
open();
|
||||||
|
ArrayList matches= new ArrayList();
|
||||||
|
setFirstFile();
|
||||||
|
while (hasMoreFiles()) {
|
||||||
|
IndexedFile file= getCurrentFile();
|
||||||
|
if (file.getPath().indexOf(word) != -1)
|
||||||
|
matches.add(file);
|
||||||
|
moveToNextFile();
|
||||||
|
}
|
||||||
|
IQueryResult[] match= new IQueryResult[matches.size()];
|
||||||
|
matches.toArray(match);
|
||||||
|
return match;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @see IndexInput#setFirstFile()
|
||||||
|
*/
|
||||||
|
|
||||||
|
protected void setFirstFile() throws IOException {
|
||||||
|
filePosition= 1;
|
||||||
|
if (getNumFiles() > 0) {
|
||||||
|
currentFileListBlockNum= summary.getBlockNumForFileNum(1);
|
||||||
|
currentFileListBlock= getFileListBlock(currentFileListBlockNum);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @see IndexInput#setFirstWord()
|
||||||
|
*/
|
||||||
|
|
||||||
|
protected void setFirstWord() throws IOException {
|
||||||
|
wordPosition= 1;
|
||||||
|
if (getNumWords() > 0) {
|
||||||
|
currentIndexBlockNum= summary.getFirstWordBlockNum();
|
||||||
|
currentIndexBlock= getIndexBlock(currentIndexBlockNum);
|
||||||
|
currentWordEntry= new WordEntry();
|
||||||
|
currentIndexBlock.reset();
|
||||||
|
currentIndexBlock.nextEntry(currentWordEntry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,167 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2003 IBM Corporation and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Common Public License v0.5
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/cpl-v05.html
|
||||||
|
******************************************************************************/
|
||||||
|
/*
|
||||||
|
* Created on Jun 1, 2003
|
||||||
|
*/
|
||||||
|
package org.eclipse.cdt.internal.core.index.impl;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.RandomAccessFile;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A blocksIndexOutput is used to save an index in a file with the given structure:<br>
|
||||||
|
* - Signature of the file;<br>
|
||||||
|
* - FileListBlocks;<br>
|
||||||
|
* - IndexBlocks;<br>
|
||||||
|
* - Summary of the index.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class BlocksIndexOutput extends IndexOutput {
|
||||||
|
protected RandomAccessFile indexOut;
|
||||||
|
protected int blockNum;
|
||||||
|
protected boolean opened= false;
|
||||||
|
protected File indexFile;
|
||||||
|
protected FileListBlock fileListBlock;
|
||||||
|
protected IndexBlock indexBlock;
|
||||||
|
protected int numWords= 0;
|
||||||
|
protected IndexSummary summary;
|
||||||
|
protected int numFiles= 0;
|
||||||
|
protected boolean firstInBlock;
|
||||||
|
protected boolean firstIndexBlock;
|
||||||
|
protected boolean firstFileListBlock;
|
||||||
|
|
||||||
|
public BlocksIndexOutput(File indexFile) {
|
||||||
|
this.indexFile= indexFile;
|
||||||
|
summary= new IndexSummary();
|
||||||
|
blockNum= 1;
|
||||||
|
firstInBlock= true;
|
||||||
|
firstIndexBlock= true;
|
||||||
|
firstFileListBlock= true;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @see IndexOutput#addFile
|
||||||
|
*/
|
||||||
|
public void addFile(IndexedFile indexedFile) throws IOException {
|
||||||
|
if (firstFileListBlock) {
|
||||||
|
firstInBlock= true;
|
||||||
|
fileListBlock= new FileListBlock(IIndexConstants.BLOCK_SIZE);
|
||||||
|
firstFileListBlock= false;
|
||||||
|
}
|
||||||
|
if (fileListBlock.addFile(indexedFile)) {
|
||||||
|
if (firstInBlock) {
|
||||||
|
summary.addFirstFileInBlock(indexedFile, blockNum);
|
||||||
|
firstInBlock= false;
|
||||||
|
}
|
||||||
|
numFiles++;
|
||||||
|
} else {
|
||||||
|
if (fileListBlock.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
flushFiles();
|
||||||
|
addFile(indexedFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @see IndexOutput#addWord
|
||||||
|
*/
|
||||||
|
public void addWord(WordEntry entry) throws IOException {
|
||||||
|
if (firstIndexBlock) {
|
||||||
|
indexBlock= new GammaCompressedIndexBlock(IIndexConstants.BLOCK_SIZE);
|
||||||
|
firstInBlock= true;
|
||||||
|
firstIndexBlock= false;
|
||||||
|
}
|
||||||
|
if (entry.getNumRefs() == 0)
|
||||||
|
return;
|
||||||
|
if (indexBlock.addEntry(entry)) {
|
||||||
|
if (firstInBlock) {
|
||||||
|
summary.addFirstWordInBlock(entry.getWord(), blockNum);
|
||||||
|
firstInBlock= false;
|
||||||
|
}
|
||||||
|
numWords++;
|
||||||
|
} else {
|
||||||
|
if (indexBlock.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
flushWords();
|
||||||
|
addWord(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @see IndexOutput#close
|
||||||
|
*/
|
||||||
|
public void close() throws IOException {
|
||||||
|
if (opened) {
|
||||||
|
indexOut.close();
|
||||||
|
summary= null;
|
||||||
|
numFiles= 0;
|
||||||
|
opened= false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @see IndexOutput#flush
|
||||||
|
*/
|
||||||
|
public void flush() throws IOException {
|
||||||
|
|
||||||
|
summary.setNumFiles(numFiles);
|
||||||
|
summary.setNumWords(numWords);
|
||||||
|
indexOut.seek(blockNum * (long) IIndexConstants.BLOCK_SIZE);
|
||||||
|
summary.write(indexOut);
|
||||||
|
indexOut.seek(0);
|
||||||
|
indexOut.writeUTF(IIndexConstants.SIGNATURE);
|
||||||
|
indexOut.writeInt(blockNum);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Writes the current fileListBlock on the disk and initialises it
|
||||||
|
* (when it's full or it's the end of the index).
|
||||||
|
*/
|
||||||
|
protected void flushFiles() throws IOException {
|
||||||
|
if (!firstFileListBlock
|
||||||
|
&& fileListBlock != null) {
|
||||||
|
fileListBlock.flush();
|
||||||
|
fileListBlock.write(indexOut, blockNum++);
|
||||||
|
fileListBlock.clear();
|
||||||
|
firstInBlock= true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Writes the current indexBlock on the disk and initialises it
|
||||||
|
* (when it's full or it's the end of the index).
|
||||||
|
*/
|
||||||
|
protected void flushWords() throws IOException {
|
||||||
|
if (!firstInBlock
|
||||||
|
&& indexBlock != null) { // could have added a document without any indexed word, no block created yet
|
||||||
|
indexBlock.flush();
|
||||||
|
indexBlock.write(indexOut, blockNum++);
|
||||||
|
indexBlock.clear();
|
||||||
|
firstInBlock= true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @see IndexOutput#getDestination
|
||||||
|
*/
|
||||||
|
public Object getDestination() {
|
||||||
|
return indexFile;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @see IndexOutput#open
|
||||||
|
*/
|
||||||
|
public void open() throws IOException {
|
||||||
|
if (!opened) {
|
||||||
|
summary= new IndexSummary();
|
||||||
|
numFiles= 0;
|
||||||
|
numWords= 0;
|
||||||
|
blockNum= 1;
|
||||||
|
firstInBlock= true;
|
||||||
|
firstIndexBlock= true;
|
||||||
|
firstFileListBlock= true;
|
||||||
|
indexOut= new SafeRandomAccessFile(this.indexFile, "rw"); //$NON-NLS-1$
|
||||||
|
opened= true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,343 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2003 IBM Corporation and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Common Public License v0.5
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/cpl-v05.html
|
||||||
|
******************************************************************************/
|
||||||
|
/*
|
||||||
|
* Created on Jun 1, 2003
|
||||||
|
*/
|
||||||
|
package org.eclipse.cdt.internal.core.index.impl;
|
||||||
|
|
||||||
|
import java.io.UTFDataFormatException;
|
||||||
|
|
||||||
|
public class CodeByteStream {
|
||||||
|
protected byte[] bytes;
|
||||||
|
protected int byteOffset= 0;
|
||||||
|
protected int bitOffset= 0;
|
||||||
|
protected int markByteOffset= -1;
|
||||||
|
protected int markBitOffset= -1;
|
||||||
|
|
||||||
|
public CodeByteStream() {
|
||||||
|
this(16);
|
||||||
|
}
|
||||||
|
public CodeByteStream(byte[] bytes) {
|
||||||
|
this.bytes= bytes;
|
||||||
|
}
|
||||||
|
public CodeByteStream(int initialByteLength) {
|
||||||
|
bytes= new byte[initialByteLength];
|
||||||
|
}
|
||||||
|
public int byteLength() {
|
||||||
|
return (bitOffset + 7) / 8 + byteOffset;
|
||||||
|
}
|
||||||
|
public byte[] getBytes(int startOffset, int endOffset) {
|
||||||
|
int byteLength= byteLength();
|
||||||
|
if (startOffset > byteLength || endOffset > byteLength || startOffset > endOffset)
|
||||||
|
throw new IndexOutOfBoundsException();
|
||||||
|
int length= endOffset - startOffset;
|
||||||
|
byte[] result= new byte[length];
|
||||||
|
System.arraycopy(bytes, startOffset, result, 0, length);
|
||||||
|
if (endOffset == byteLength && bitOffset != 0) {
|
||||||
|
int mask= (1 << bitOffset) - 1;
|
||||||
|
result[length - 1] &= (mask << 8 - bitOffset);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
protected void grow() {
|
||||||
|
byte[] newBytes= new byte[bytes.length * 2 + 1];
|
||||||
|
System.arraycopy(bytes, 0, newBytes, 0, bytes.length);
|
||||||
|
bytes= newBytes;
|
||||||
|
}
|
||||||
|
public void mark() {
|
||||||
|
markByteOffset= byteOffset;
|
||||||
|
markBitOffset= bitOffset;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Reads a single bit (value == 0 or == 1).
|
||||||
|
*/
|
||||||
|
public int readBit() {
|
||||||
|
int value= (bytes[byteOffset] >> (7 - bitOffset)) & 1;
|
||||||
|
if (++bitOffset >= 8) {
|
||||||
|
bitOffset= 0;
|
||||||
|
++byteOffset;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Read up to 32 bits from the stream.
|
||||||
|
*/
|
||||||
|
public int readBits(int numBits) {
|
||||||
|
int value= 0;
|
||||||
|
while (numBits > 0) {
|
||||||
|
int bitsToRead= 8 - bitOffset;
|
||||||
|
if (bitsToRead > numBits)
|
||||||
|
bitsToRead= numBits;
|
||||||
|
int mask= (1 << bitsToRead) - 1;
|
||||||
|
value |= ((bytes[byteOffset] >> (8 - bitOffset - bitsToRead)) & mask) << (numBits - bitsToRead);
|
||||||
|
numBits -= bitsToRead;
|
||||||
|
bitOffset += bitsToRead;
|
||||||
|
if (bitOffset >= 8) {
|
||||||
|
bitOffset -= 8;
|
||||||
|
byteOffset += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
public final int readByte() {
|
||||||
|
|
||||||
|
// no need to rebuild byte value from bit sequences
|
||||||
|
if (bitOffset == 0) return bytes[byteOffset++] & 255;
|
||||||
|
|
||||||
|
int value= 0;
|
||||||
|
int numBits = 8;
|
||||||
|
while (numBits > 0) {
|
||||||
|
int bitsToRead= 8 - bitOffset;
|
||||||
|
if (bitsToRead > numBits)
|
||||||
|
bitsToRead= numBits;
|
||||||
|
int mask= (1 << bitsToRead) - 1;
|
||||||
|
value |= ((bytes[byteOffset] >> (8 - bitOffset - bitsToRead)) & mask) << (numBits - bitsToRead);
|
||||||
|
numBits -= bitsToRead;
|
||||||
|
bitOffset += bitsToRead;
|
||||||
|
if (bitOffset >= 8) {
|
||||||
|
bitOffset -= 8;
|
||||||
|
byteOffset += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Reads a value using Gamma coding.
|
||||||
|
*/
|
||||||
|
public int readGamma() {
|
||||||
|
int numBits= readUnary();
|
||||||
|
return readBits(numBits - 1) | (1 << (numBits - 1));
|
||||||
|
}
|
||||||
|
public char[] readUTF() throws UTFDataFormatException {
|
||||||
|
int utflen= readByte();
|
||||||
|
if (utflen == 255) {
|
||||||
|
// long UTF
|
||||||
|
int high = readByte();
|
||||||
|
int low = readByte();
|
||||||
|
utflen = (high << 8) + low;
|
||||||
|
}
|
||||||
|
char str[]= new char[utflen];
|
||||||
|
int count= 0;
|
||||||
|
int strlen= 0;
|
||||||
|
while (count < utflen) {
|
||||||
|
int c= readByte();
|
||||||
|
int char2, char3;
|
||||||
|
switch (c >> 4) {
|
||||||
|
case 0 :
|
||||||
|
case 1 :
|
||||||
|
case 2 :
|
||||||
|
case 3 :
|
||||||
|
case 4 :
|
||||||
|
case 5 :
|
||||||
|
case 6 :
|
||||||
|
case 7 :
|
||||||
|
// 0xxxxxxx
|
||||||
|
count++;
|
||||||
|
str[strlen++]= (char) c;
|
||||||
|
break;
|
||||||
|
case 12 :
|
||||||
|
case 13 :
|
||||||
|
// 110x xxxx 10xx xxxx
|
||||||
|
count += 2;
|
||||||
|
if (count > utflen)
|
||||||
|
throw new UTFDataFormatException();
|
||||||
|
char2= readByte();
|
||||||
|
if ((char2 & 0xC0) != 0x80)
|
||||||
|
throw new UTFDataFormatException();
|
||||||
|
str[strlen++]= (char) (((c & 0x1F) << 6) | (char2 & 0x3F));
|
||||||
|
break;
|
||||||
|
case 14 :
|
||||||
|
// 1110 xxxx 10xx xxxx 10xx xxxx
|
||||||
|
count += 3;
|
||||||
|
if (count > utflen)
|
||||||
|
throw new UTFDataFormatException();
|
||||||
|
char2= readByte();
|
||||||
|
char3= readByte();
|
||||||
|
if (((char2 & 0xC0) != 0x80) || ((char3 & 0xC0) != 0x80))
|
||||||
|
throw new UTFDataFormatException();
|
||||||
|
str[strlen++]= (char) (((c & 0x0F) << 12) | ((char2 & 0x3F) << 6) | ((char3 & 0x3F) << 0));
|
||||||
|
break;
|
||||||
|
default :
|
||||||
|
// 10xx xxxx, 1111 xxxx
|
||||||
|
throw new UTFDataFormatException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (strlen < utflen)
|
||||||
|
System.arraycopy(str, 0, str= new char[strlen], 0, strlen);
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Reads a value in unary.
|
||||||
|
*/
|
||||||
|
public int readUnary() {
|
||||||
|
int value= 1;
|
||||||
|
int mask= 1 << (7 - bitOffset);
|
||||||
|
while ((bytes[byteOffset] & mask) != 0) {
|
||||||
|
++value;
|
||||||
|
if (++bitOffset >= 8) {
|
||||||
|
bitOffset= 0;
|
||||||
|
++byteOffset;
|
||||||
|
mask= 0x80;
|
||||||
|
} else {
|
||||||
|
mask >>>= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// skip the 0 bit
|
||||||
|
if (++bitOffset >= 8) {
|
||||||
|
bitOffset= 0;
|
||||||
|
++byteOffset;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
public void reset() {
|
||||||
|
byteOffset= bitOffset= 0;
|
||||||
|
markByteOffset= markBitOffset= -1;
|
||||||
|
}
|
||||||
|
public void reset(byte[] bytes) {
|
||||||
|
this.bytes= bytes;
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
public void reset(byte[] bytes, int byteOffset) {
|
||||||
|
reset(bytes);
|
||||||
|
this.byteOffset= byteOffset;
|
||||||
|
}
|
||||||
|
public boolean resetToMark() {
|
||||||
|
if (markByteOffset == -1)
|
||||||
|
return false;
|
||||||
|
byteOffset= markByteOffset;
|
||||||
|
bitOffset= markBitOffset;
|
||||||
|
markByteOffset= markBitOffset= -1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
public void skipBits(int numBits) {
|
||||||
|
int newOffset= byteOffset * 8 + bitOffset + numBits;
|
||||||
|
if (newOffset < 0 || (newOffset + 7) / 8 >= bytes.length)
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
byteOffset= newOffset / 8;
|
||||||
|
bitOffset= newOffset % 8;
|
||||||
|
}
|
||||||
|
public byte[] toByteArray() {
|
||||||
|
return getBytes(0, byteLength());
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Writes a single bit (value == 0 or == 1).
|
||||||
|
*/
|
||||||
|
public void writeBit(int value) {
|
||||||
|
bytes[byteOffset] |= (value & 1) << (7 - bitOffset);
|
||||||
|
if (++bitOffset >= 8) {
|
||||||
|
bitOffset= 0;
|
||||||
|
if (++byteOffset >= bytes.length)
|
||||||
|
grow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Write up to 32 bits to the stream.
|
||||||
|
* The least significant numBits bits of value are written.
|
||||||
|
*/
|
||||||
|
public void writeBits(int value, int numBits) {
|
||||||
|
while (numBits > 0) {
|
||||||
|
int bitsToWrite= 8 - bitOffset;
|
||||||
|
if (bitsToWrite > numBits)
|
||||||
|
bitsToWrite= numBits;
|
||||||
|
int shift= 8 - bitOffset - bitsToWrite;
|
||||||
|
int mask= ((1 << bitsToWrite) - 1) << shift;
|
||||||
|
bytes[byteOffset]= (byte) ((bytes[byteOffset] & ~mask) | (((value >>> (numBits - bitsToWrite)) << shift) & mask));
|
||||||
|
numBits -= bitsToWrite;
|
||||||
|
bitOffset += bitsToWrite;
|
||||||
|
if (bitOffset >= 8) {
|
||||||
|
bitOffset -= 8;
|
||||||
|
if (++byteOffset >= bytes.length)
|
||||||
|
grow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void writeByte(int value) {
|
||||||
|
writeBits(value, 8);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Writes the given value using Gamma coding, in which positive integer x
|
||||||
|
* is represented by coding floor(log2(x) in unary followed by the value
|
||||||
|
* of x - 2**floor(log2(x)) in binary.
|
||||||
|
* The value must be >= 1.
|
||||||
|
*/
|
||||||
|
public void writeGamma(int value) {
|
||||||
|
if (value < 1)
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
int temp= value;
|
||||||
|
int numBits= 0;
|
||||||
|
while (temp != 0) {
|
||||||
|
temp >>>= 1;
|
||||||
|
++numBits;
|
||||||
|
}
|
||||||
|
writeUnary(numBits);
|
||||||
|
writeBits(value, numBits - 1);
|
||||||
|
}
|
||||||
|
public void writeUTF(char[] str, int start, int end) {
|
||||||
|
int utflen= 0;
|
||||||
|
for (int i= start; i < end; i++) {
|
||||||
|
int c= str[i];
|
||||||
|
if ((c >= 0x0001) && (c <= 0x007F)) {
|
||||||
|
utflen++;
|
||||||
|
} else if (c > 0x07FF) {
|
||||||
|
utflen += 3;
|
||||||
|
} else {
|
||||||
|
utflen += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (utflen < 255) {
|
||||||
|
writeByte(utflen & 0xFF);
|
||||||
|
} else if (utflen > 65535) {
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
} else {
|
||||||
|
writeByte(255); // marker for long UTF
|
||||||
|
writeByte((utflen >>> 8) & 0xFF); // high byte
|
||||||
|
writeByte((utflen >>> 0) & 0xFF); // low byte
|
||||||
|
}
|
||||||
|
for (int i= start; i < end; i++) {
|
||||||
|
int c= str[i];
|
||||||
|
if ((c >= 0x0001) && (c <= 0x007F)) {
|
||||||
|
writeByte(c);
|
||||||
|
} else if (c > 0x07FF) {
|
||||||
|
writeByte(0xE0 | ((c >> 12) & 0x0F));
|
||||||
|
writeByte(0x80 | ((c >> 6) & 0x3F));
|
||||||
|
writeByte(0x80 | ((c >> 0) & 0x3F));
|
||||||
|
} else {
|
||||||
|
writeByte(0xC0 | ((c >> 6) & 0x1F));
|
||||||
|
writeByte(0x80 | ((c >> 0) & 0x3F));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Write the given value in unary. The value must be >= 1.
|
||||||
|
*/
|
||||||
|
public void writeUnary(int value) {
|
||||||
|
if (value < 1)
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
int mask= 1 << (7 - bitOffset);
|
||||||
|
// write N-1 1-bits
|
||||||
|
while (--value > 0) {
|
||||||
|
bytes[byteOffset] |= mask;
|
||||||
|
if (++bitOffset >= 8) {
|
||||||
|
bitOffset= 0;
|
||||||
|
if (++byteOffset >= bytes.length)
|
||||||
|
grow();
|
||||||
|
mask= 0x80;
|
||||||
|
} else {
|
||||||
|
mask >>>= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// write a 0-bit
|
||||||
|
bytes[byteOffset] &= ~mask;
|
||||||
|
if (++bitOffset >= 8) {
|
||||||
|
bitOffset= 0;
|
||||||
|
if (++byteOffset >= bytes.length)
|
||||||
|
grow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2003 IBM Corporation and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Common Public License v0.5
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/cpl-v05.html
|
||||||
|
******************************************************************************/
|
||||||
|
/*
|
||||||
|
* Created on Jun 1, 2003
|
||||||
|
*/
|
||||||
|
package org.eclipse.cdt.internal.core.index.impl;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.internal.core.index.IEntryResult;
|
||||||
|
import org.eclipse.cdt.internal.core.search.CharOperation;
|
||||||
|
|
||||||
|
|
||||||
|
public class EntryResult implements IEntryResult {
|
||||||
|
private char[] word;
|
||||||
|
private int[] fileRefs;
|
||||||
|
|
||||||
|
public EntryResult(char[] word, int[] refs) {
|
||||||
|
this.word = word;
|
||||||
|
this.fileRefs = refs;
|
||||||
|
}
|
||||||
|
public boolean equals(Object anObject){
|
||||||
|
|
||||||
|
if (this == anObject) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if ((anObject != null) && (anObject instanceof EntryResult)) {
|
||||||
|
EntryResult anEntryResult = (EntryResult) anObject;
|
||||||
|
if (!CharOperation.equals(this.word, anEntryResult.word)) return false;
|
||||||
|
|
||||||
|
int length;
|
||||||
|
int[] refs, otherRefs;
|
||||||
|
if ((length = (refs = this.fileRefs).length) != (otherRefs = anEntryResult.fileRefs).length) return false;
|
||||||
|
for (int i = 0; i < length; i++){
|
||||||
|
if (refs[i] != otherRefs[i]) return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
public int[] getFileReferences() {
|
||||||
|
return fileRefs;
|
||||||
|
}
|
||||||
|
public char[] getWord() {
|
||||||
|
return word;
|
||||||
|
}
|
||||||
|
public int hashCode(){
|
||||||
|
return CharOperation.hashCode(word);
|
||||||
|
}
|
||||||
|
public String toString(){
|
||||||
|
StringBuffer buffer = new StringBuffer(word.length * 2);
|
||||||
|
buffer.append("EntryResult: word="); //$NON-NLS-1$
|
||||||
|
buffer.append(word);
|
||||||
|
buffer.append(", refs={"); //$NON-NLS-1$
|
||||||
|
for (int i = 0; i < fileRefs.length; i++){
|
||||||
|
if (i > 0) buffer.append(',');
|
||||||
|
buffer.append(' ');
|
||||||
|
buffer.append(fileRefs[i]);
|
||||||
|
}
|
||||||
|
buffer.append(" }"); //$NON-NLS-1$
|
||||||
|
return buffer.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,382 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2003 IBM Corporation and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Common Public License v0.5
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/cpl-v05.html
|
||||||
|
******************************************************************************/
|
||||||
|
/*
|
||||||
|
* Created on Jun 1, 2003
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.eclipse.cdt.internal.core.index.impl;
|
||||||
|
|
||||||
|
import java.io.UTFDataFormatException;
|
||||||
|
|
||||||
|
public class Field {
|
||||||
|
protected byte[] buffer; // contents
|
||||||
|
protected int offset; // offset of the field within the byte array
|
||||||
|
protected int length; // length of the field
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ByteSegment constructor comment.
|
||||||
|
*/
|
||||||
|
public Field(byte[] bytes) {
|
||||||
|
this.buffer= bytes;
|
||||||
|
this.offset= 0;
|
||||||
|
this.length= bytes.length;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* ByteSegment constructor comment.
|
||||||
|
*/
|
||||||
|
public Field(byte[] bytes, int length) {
|
||||||
|
this.buffer= bytes;
|
||||||
|
this.offset= 0;
|
||||||
|
this.length= length;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* ByteSegment constructor comment.
|
||||||
|
*/
|
||||||
|
public Field(byte[] bytes, int offset, int length) {
|
||||||
|
this.buffer= bytes;
|
||||||
|
this.offset= offset;
|
||||||
|
this.length= length;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Creates a new field containing an empty buffer of the given length.
|
||||||
|
*/
|
||||||
|
public Field(int length) {
|
||||||
|
this.buffer= new byte[length];
|
||||||
|
this.offset= 0;
|
||||||
|
this.length= length;
|
||||||
|
}
|
||||||
|
public byte[] buffer() {
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
public Field buffer(byte[] buffer) {
|
||||||
|
this.buffer= buffer;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
public Field clear() {
|
||||||
|
clear(buffer, offset, length);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
protected static void clear(byte[] buffer, int offset, int length) {
|
||||||
|
int n= offset;
|
||||||
|
for (int i= 0; i < length; i++) {
|
||||||
|
buffer[n]= 0;
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public Field clear(int length) {
|
||||||
|
clear(buffer, offset, length);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
public Field clear(int offset, int length) {
|
||||||
|
clear(buffer, this.offset + offset, length);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
protected static int compare(byte[] buffer1, int offset1, int length1, byte[] buffer2, int offset2, int length2) {
|
||||||
|
int n= Math.min(length1, length2);
|
||||||
|
for (int i= 0; i < n; i++) {
|
||||||
|
int j1= buffer1[offset1 + i] & 255;
|
||||||
|
int j2= buffer2[offset2 + i] & 255;
|
||||||
|
if (j1 > j2)
|
||||||
|
return 1;
|
||||||
|
if (j1 < j2)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (length1 > n) {
|
||||||
|
for (int i= n; i < length1; i++)
|
||||||
|
if (buffer1[offset1 + i] != 0)
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
for (int i= n; i < length2; i++)
|
||||||
|
if (buffer2[offset2 + i] != 0)
|
||||||
|
return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
public static int compare(Field f1, Field f2) {
|
||||||
|
return compare(f1.buffer, f1.offset, f1.length, f2.buffer, f2.offset, f2.length);
|
||||||
|
}
|
||||||
|
// copy bytes from one offset to another within the field
|
||||||
|
public Field copy(int fromOffset, int toOffset, int length) {
|
||||||
|
System.arraycopy(buffer, offset + fromOffset, buffer, offset + toOffset, length);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
public Field dec(int n) {
|
||||||
|
offset -= n;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
public byte[] get() {
|
||||||
|
byte[] result= new byte[length];
|
||||||
|
System.arraycopy(buffer, offset, result, 0, length);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
public byte[] get(int offset, int length) {
|
||||||
|
byte[] result= new byte[length];
|
||||||
|
System.arraycopy(buffer, this.offset + offset, result, 0, length);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
public Field getField(int offset, int length) {
|
||||||
|
return new Field(buffer, this.offset + offset, length);
|
||||||
|
}
|
||||||
|
public int getInt1() {
|
||||||
|
return buffer[this.offset];
|
||||||
|
}
|
||||||
|
public int getInt1(int offset) {
|
||||||
|
return buffer[this.offset + offset];
|
||||||
|
}
|
||||||
|
public int getInt2() {
|
||||||
|
int i= this.offset;
|
||||||
|
int v= buffer[i++];
|
||||||
|
v= (v << 8) | (buffer[i++] & 255);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
public int getInt2(int offset) {
|
||||||
|
int i= this.offset + offset;
|
||||||
|
int v= buffer[i++];
|
||||||
|
v= (v << 8) | (buffer[i++] & 255);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
public int getInt3() {
|
||||||
|
int i= this.offset;
|
||||||
|
int v= buffer[i++];
|
||||||
|
v= (v << 8) | (buffer[i++] & 255);
|
||||||
|
v= (v << 8) | (buffer[i++] & 255);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
public int getInt3(int offset) {
|
||||||
|
int i= this.offset + offset;
|
||||||
|
int v= buffer[i++];
|
||||||
|
v= (v << 8) | (buffer[i++] & 255);
|
||||||
|
v= (v << 8) | (buffer[i++] & 255);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
public int getInt4() {
|
||||||
|
int i= this.offset;
|
||||||
|
int v= buffer[i++];
|
||||||
|
v= (v << 8) | (buffer[i++] & 255);
|
||||||
|
v= (v << 8) | (buffer[i++] & 255);
|
||||||
|
v= (v << 8) | (buffer[i++] & 255);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
public int getInt4(int offset) {
|
||||||
|
int i= this.offset + offset;
|
||||||
|
int v= buffer[i++];
|
||||||
|
v= (v << 8) | (buffer[i++] & 255);
|
||||||
|
v= (v << 8) | (buffer[i++] & 255);
|
||||||
|
v= (v << 8) | (buffer[i++] & 255);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
public int getUInt1() {
|
||||||
|
return buffer[this.offset] & 255;
|
||||||
|
}
|
||||||
|
public int getUInt1(int offset) {
|
||||||
|
return buffer[this.offset + offset] & 255;
|
||||||
|
}
|
||||||
|
public int getUInt2() {
|
||||||
|
int i= this.offset;
|
||||||
|
int v= (buffer[i++] & 255);
|
||||||
|
v= (v << 8) | (buffer[i++] & 255);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
public int getUInt2(int offset) {
|
||||||
|
int i= this.offset + offset;
|
||||||
|
int v= (buffer[i++] & 255);
|
||||||
|
v= (v << 8) | (buffer[i++] & 255);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
public int getUInt3() {
|
||||||
|
int i= this.offset;
|
||||||
|
int v= (buffer[i++] & 255);
|
||||||
|
v= (v << 8) | (buffer[i++] & 255);
|
||||||
|
v= (v << 8) | (buffer[i++] & 255);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
public int getUInt3(int offset) {
|
||||||
|
int i= this.offset + offset;
|
||||||
|
int v= (buffer[i++] & 255);
|
||||||
|
v= (v << 8) | (buffer[i++] & 255);
|
||||||
|
v= (v << 8) | (buffer[i++] & 255);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
public char[] getUTF(int offset) throws UTFDataFormatException {
|
||||||
|
int pos= this.offset + offset;
|
||||||
|
int utflen= getUInt2(pos);
|
||||||
|
pos += 2;
|
||||||
|
char str[]= new char[utflen];
|
||||||
|
int count= 0;
|
||||||
|
int strlen= 0;
|
||||||
|
while (count < utflen) {
|
||||||
|
int c= buffer[pos++] & 0xFF;
|
||||||
|
int char2, char3;
|
||||||
|
switch (c >> 4) {
|
||||||
|
case 0 :
|
||||||
|
case 1 :
|
||||||
|
case 2 :
|
||||||
|
case 3 :
|
||||||
|
case 4 :
|
||||||
|
case 5 :
|
||||||
|
case 6 :
|
||||||
|
case 7 :
|
||||||
|
// 0xxxxxxx
|
||||||
|
count++;
|
||||||
|
str[strlen++]= (char) c;
|
||||||
|
break;
|
||||||
|
case 12 :
|
||||||
|
case 13 :
|
||||||
|
// 110x xxxx 10xx xxxx
|
||||||
|
count += 2;
|
||||||
|
if (count > utflen)
|
||||||
|
throw new UTFDataFormatException();
|
||||||
|
char2= buffer[pos++] & 0xFF;
|
||||||
|
if ((char2 & 0xC0) != 0x80)
|
||||||
|
throw new UTFDataFormatException();
|
||||||
|
str[strlen++]= (char) (((c & 0x1F) << 6) | (char2 & 0x3F));
|
||||||
|
break;
|
||||||
|
case 14 :
|
||||||
|
// 1110 xxxx 10xx xxxx 10xx xxxx
|
||||||
|
count += 3;
|
||||||
|
if (count > utflen)
|
||||||
|
throw new UTFDataFormatException();
|
||||||
|
char2= buffer[pos++] & 0xFF;
|
||||||
|
char3= buffer[pos++] & 0xFF;
|
||||||
|
if (((char2 & 0xC0) != 0x80) || ((char3 & 0xC0) != 0x80))
|
||||||
|
throw new UTFDataFormatException();
|
||||||
|
str[strlen++]= (char) (((c & 0x0F) << 12) | ((char2 & 0x3F) << 6) | ((char3 & 0x3F) << 0));
|
||||||
|
break;
|
||||||
|
default :
|
||||||
|
// 10xx xxxx, 1111 xxxx
|
||||||
|
throw new UTFDataFormatException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (strlen < utflen)
|
||||||
|
System.arraycopy(str, 0, str= new char[strlen], 0, strlen);
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
public Field inc(int n) {
|
||||||
|
offset += n;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
public int length() {
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
public Field length(int length) {
|
||||||
|
this.length= length;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
Returns the offset into the underlying byte array that this field is defined over.
|
||||||
|
*/
|
||||||
|
public int offset() {
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
public Field offset(int offset) {
|
||||||
|
this.offset= offset;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
public Field pointTo(int offset) {
|
||||||
|
return new Field(buffer, this.offset + offset, 0);
|
||||||
|
}
|
||||||
|
public Field put(byte[] b) {
|
||||||
|
return put(0, b);
|
||||||
|
}
|
||||||
|
public Field put(int offset, byte[] b) {
|
||||||
|
System.arraycopy(b, 0, buffer, this.offset + offset, b.length);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
public Field put(int offset, Field f) {
|
||||||
|
System.arraycopy(f.buffer, f.offset, buffer, this.offset + offset, f.length);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
public Field put(Field f) {
|
||||||
|
System.arraycopy(f.buffer, f.offset, buffer, offset, f.length);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
public Field putInt1(int n) {
|
||||||
|
buffer[offset]= (byte) (n);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
public Field putInt1(int offset, int n) {
|
||||||
|
buffer[this.offset + offset]= (byte) (n);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
public Field putInt2(int n) {
|
||||||
|
int i= offset;
|
||||||
|
buffer[i++]= (byte) (n >> 8);
|
||||||
|
buffer[i++]= (byte) (n >> 0);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
public Field putInt2(int offset, int n) {
|
||||||
|
int i= this.offset + offset;
|
||||||
|
buffer[i++]= (byte) (n >> 8);
|
||||||
|
buffer[i++]= (byte) (n >> 0);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
public Field putInt3(int n) {
|
||||||
|
int i= offset;
|
||||||
|
buffer[i++]= (byte) (n >> 16);
|
||||||
|
buffer[i++]= (byte) (n >> 8);
|
||||||
|
buffer[i++]= (byte) (n >> 0);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
public Field putInt3(int offset, int n) {
|
||||||
|
int i= this.offset + offset;
|
||||||
|
buffer[i++]= (byte) (n >> 16);
|
||||||
|
buffer[i++]= (byte) (n >> 8);
|
||||||
|
buffer[i++]= (byte) (n >> 0);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
public Field putInt4(int n) {
|
||||||
|
int i= offset;
|
||||||
|
buffer[i++]= (byte) (n >> 24);
|
||||||
|
buffer[i++]= (byte) (n >> 16);
|
||||||
|
buffer[i++]= (byte) (n >> 8);
|
||||||
|
buffer[i++]= (byte) (n >> 0);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
public Field putInt4(int offset, int n) {
|
||||||
|
int i= this.offset + offset;
|
||||||
|
buffer[i++]= (byte) (n >> 24);
|
||||||
|
buffer[i++]= (byte) (n >> 16);
|
||||||
|
buffer[i++]= (byte) (n >> 8);
|
||||||
|
buffer[i++]= (byte) (n >> 0);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
public int putUTF(int offset, char[] str) {
|
||||||
|
int strlen= str.length;
|
||||||
|
int utflen= 0;
|
||||||
|
for (int i= 0; i < strlen; i++) {
|
||||||
|
int c= str[i];
|
||||||
|
if ((c >= 0x0001) && (c <= 0x007F)) {
|
||||||
|
utflen++;
|
||||||
|
} else if (c > 0x07FF) {
|
||||||
|
utflen += 3;
|
||||||
|
} else {
|
||||||
|
utflen += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (utflen > 65535)
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
int pos= this.offset + offset;
|
||||||
|
buffer[pos++]= (byte) ((utflen >>> 8) & 0xFF);
|
||||||
|
buffer[pos++]= (byte) ((utflen >>> 0) & 0xFF);
|
||||||
|
for (int i= 0; i < strlen; i++) {
|
||||||
|
int c= str[i];
|
||||||
|
if ((c >= 0x0001) && (c <= 0x007F)) {
|
||||||
|
buffer[pos++]= ((byte) c);
|
||||||
|
} else if (c > 0x07FF) {
|
||||||
|
buffer[pos++]= ((byte) (0xE0 | ((c >> 12) & 0x0F)));
|
||||||
|
buffer[pos++]= ((byte) (0x80 | ((c >> 6) & 0x3F)));
|
||||||
|
buffer[pos++]= ((byte) (0x80 | ((c >> 0) & 0x3F)));
|
||||||
|
} else {
|
||||||
|
buffer[pos++]= ((byte) (0xC0 | ((c >> 6) & 0x1F)));
|
||||||
|
buffer[pos++]= ((byte) (0x80 | ((c >> 0) & 0x3F)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 2 + utflen;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,110 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2003 IBM Corporation and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Common Public License v0.5
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/cpl-v05.html
|
||||||
|
******************************************************************************/
|
||||||
|
/*
|
||||||
|
* Created on Jun 1, 2003
|
||||||
|
*/
|
||||||
|
package org.eclipse.cdt.internal.core.index.impl;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public class FileListBlock extends Block {
|
||||||
|
|
||||||
|
protected int offset= 0;
|
||||||
|
protected String prevPath= null;
|
||||||
|
protected String[] paths= null;
|
||||||
|
|
||||||
|
public FileListBlock(int blockSize) {
|
||||||
|
super(blockSize);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* add the name of the indexedfile to the buffr of the field.
|
||||||
|
* The name is not the entire name of the indexedfile, but the
|
||||||
|
* difference between its name and the name of the previous indexedfile ...
|
||||||
|
*/
|
||||||
|
public boolean addFile(IndexedFile indexedFile) {
|
||||||
|
int offset= this.offset;
|
||||||
|
if (isEmpty()) {
|
||||||
|
field.putInt4(offset, indexedFile.getFileNumber());
|
||||||
|
offset += 4;
|
||||||
|
}
|
||||||
|
String path= indexedFile.getPath();
|
||||||
|
int prefixLen= prevPath == null ? 0 : Util.prefixLength(prevPath, path);
|
||||||
|
int sizeEstimate= 2 + 2 + (path.length() - prefixLen) * 3;
|
||||||
|
if (offset + sizeEstimate > blockSize - 2)
|
||||||
|
return false;
|
||||||
|
field.putInt2(offset, prefixLen);
|
||||||
|
offset += 2;
|
||||||
|
char[] chars= new char[path.length() - prefixLen];
|
||||||
|
path.getChars(prefixLen, path.length(), chars, 0);
|
||||||
|
offset += field.putUTF(offset, chars);
|
||||||
|
this.offset= offset;
|
||||||
|
prevPath= path;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
public void clear() {
|
||||||
|
reset();
|
||||||
|
super.clear();
|
||||||
|
}
|
||||||
|
public void flush() {
|
||||||
|
if (offset > 0) {
|
||||||
|
field.putInt2(offset, 0);
|
||||||
|
field.putInt2(offset + 2, 0);
|
||||||
|
offset= 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public IndexedFile getFile(int fileNum) throws IOException {
|
||||||
|
IndexedFile resp= null;
|
||||||
|
try {
|
||||||
|
String[] paths= getPaths();
|
||||||
|
int i= fileNum - field.getInt4(0);
|
||||||
|
resp= new IndexedFile(paths[i], fileNum);
|
||||||
|
} catch (Exception e) {
|
||||||
|
//fileNum too big
|
||||||
|
}
|
||||||
|
return resp;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Creates a vector of paths reading the buffer of the field.
|
||||||
|
*/
|
||||||
|
protected String[] getPaths() throws IOException {
|
||||||
|
if (paths == null) {
|
||||||
|
ArrayList v= new ArrayList();
|
||||||
|
int offset= 4;
|
||||||
|
char[] prevPath= null;
|
||||||
|
for (;;) {
|
||||||
|
int prefixLen= field.getUInt2(offset);
|
||||||
|
offset += 2;
|
||||||
|
int utfLen= field.getUInt2(offset);
|
||||||
|
char[] path= field.getUTF(offset);
|
||||||
|
offset += 2 + utfLen;
|
||||||
|
if (prefixLen != 0) {
|
||||||
|
char[] temp= new char[prefixLen + path.length];
|
||||||
|
System.arraycopy(prevPath, 0, temp, 0, prefixLen);
|
||||||
|
System.arraycopy(path, 0, temp, prefixLen, path.length);
|
||||||
|
path= temp;
|
||||||
|
}
|
||||||
|
if (path.length == 0)
|
||||||
|
break;
|
||||||
|
v.add(new String(path));
|
||||||
|
prevPath= path;
|
||||||
|
}
|
||||||
|
paths= new String[v.size()];
|
||||||
|
v.toArray(paths);
|
||||||
|
}
|
||||||
|
return paths;
|
||||||
|
}
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return offset == 0;
|
||||||
|
}
|
||||||
|
public void reset() {
|
||||||
|
offset= 0;
|
||||||
|
prevPath= null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,118 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2003 IBM Corporation and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Common Public License v0.5
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/cpl-v05.html
|
||||||
|
******************************************************************************/
|
||||||
|
/*
|
||||||
|
* Created on Jun 1, 2003
|
||||||
|
*/
|
||||||
|
package org.eclipse.cdt.internal.core.index.impl;
|
||||||
|
|
||||||
|
import java.io.UTFDataFormatException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Uses prefix coding on words, and gamma coding of document numbers differences.
|
||||||
|
*/
|
||||||
|
public class GammaCompressedIndexBlock extends IndexBlock {
|
||||||
|
CodeByteStream writeCodeStream= new CodeByteStream();
|
||||||
|
CodeByteStream readCodeStream;
|
||||||
|
char[] prevWord= null;
|
||||||
|
int offset= 0;
|
||||||
|
|
||||||
|
public GammaCompressedIndexBlock(int blockSize) {
|
||||||
|
super(blockSize);
|
||||||
|
readCodeStream= new CodeByteStream(field.buffer());
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @see IndexBlock#addEntry
|
||||||
|
*/
|
||||||
|
public boolean addEntry(WordEntry entry) {
|
||||||
|
writeCodeStream.reset();
|
||||||
|
encodeEntry(entry, prevWord, writeCodeStream);
|
||||||
|
if (offset + writeCodeStream.byteLength() > this.blockSize - 2) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
byte[] bytes= writeCodeStream.toByteArray();
|
||||||
|
field.put(offset, bytes);
|
||||||
|
offset += bytes.length;
|
||||||
|
prevWord= entry.getWord();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
protected void encodeEntry(WordEntry entry, char[] prevWord, CodeByteStream codeStream) {
|
||||||
|
char[] word= entry.getWord();
|
||||||
|
int prefixLen= prevWord == null ? 0 : Util.prefixLength(prevWord, word);
|
||||||
|
codeStream.writeByte(prefixLen);
|
||||||
|
codeStream.writeUTF(word, prefixLen, word.length);
|
||||||
|
int n= entry.getNumRefs();
|
||||||
|
codeStream.writeGamma(n);
|
||||||
|
int prevRef= 0;
|
||||||
|
for (int i= 0; i < n; ++i) {
|
||||||
|
int ref= entry.getRef(i);
|
||||||
|
if (ref <= prevRef)
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
codeStream.writeGamma(ref - prevRef);
|
||||||
|
prevRef= ref;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @see IndexBlock#flush
|
||||||
|
*/
|
||||||
|
public void flush() {
|
||||||
|
if (offset > 0) {
|
||||||
|
field.putInt2(offset, 0);
|
||||||
|
offset= 0;
|
||||||
|
prevWord= null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @see IndexBlock#isEmpty
|
||||||
|
*/
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return offset == 0;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @see IndexBlock#nextEntry
|
||||||
|
*/
|
||||||
|
public boolean nextEntry(WordEntry entry) {
|
||||||
|
try {
|
||||||
|
readCodeStream.reset(field.buffer(), offset);
|
||||||
|
int prefixLength= readCodeStream.readByte();
|
||||||
|
char[] word= readCodeStream.readUTF();
|
||||||
|
if (prevWord != null && prefixLength > 0) {
|
||||||
|
char[] temp= new char[prefixLength + word.length];
|
||||||
|
System.arraycopy(prevWord, 0, temp, 0, prefixLength);
|
||||||
|
System.arraycopy(word, 0, temp, prefixLength, word.length);
|
||||||
|
word= temp;
|
||||||
|
}
|
||||||
|
if (word.length == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
entry.reset(word);
|
||||||
|
int n= readCodeStream.readGamma();
|
||||||
|
int prevRef= 0;
|
||||||
|
for (int i= 0; i < n; ++i) {
|
||||||
|
int ref= prevRef + readCodeStream.readGamma();
|
||||||
|
if (ref < prevRef)
|
||||||
|
throw new InternalError();
|
||||||
|
entry.addRef(ref);
|
||||||
|
prevRef= ref;
|
||||||
|
}
|
||||||
|
offset= readCodeStream.byteLength();
|
||||||
|
prevWord= word;
|
||||||
|
return true;
|
||||||
|
} catch (UTFDataFormatException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @see IndexBlock#reset
|
||||||
|
*/
|
||||||
|
public void reset() {
|
||||||
|
super.reset();
|
||||||
|
offset= 0;
|
||||||
|
prevWord= null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,98 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2003 IBM Corporation and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Common Public License v0.5
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/cpl-v05.html
|
||||||
|
******************************************************************************/
|
||||||
|
/*
|
||||||
|
* Created on May 30, 2003
|
||||||
|
*/
|
||||||
|
package org.eclipse.cdt.internal.core.index.impl;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.eclipse.core.resources.IFile;
|
||||||
|
import org.eclipse.core.runtime.IPath;
|
||||||
|
import org.eclipse.cdt.internal.core.search.CharOperation;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An <code>IFileDocument</code> represents an IFile.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class IFileDocument extends PropertyDocument {
|
||||||
|
protected IFile file;
|
||||||
|
|
||||||
|
// cached contents if needed - only one of them is used at a time
|
||||||
|
protected char[] charContents;
|
||||||
|
protected byte[] byteContents;
|
||||||
|
/**
|
||||||
|
* IFileDocument constructor comment.
|
||||||
|
*/
|
||||||
|
public IFileDocument(IFile file) {
|
||||||
|
this(file, (char[])null);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* IFileDocument constructor comment.
|
||||||
|
*/
|
||||||
|
public IFileDocument(IFile file, byte[] byteContents) {
|
||||||
|
this.file= file;
|
||||||
|
this.byteContents= byteContents;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* IFileDocument constructor comment.
|
||||||
|
*/
|
||||||
|
public IFileDocument(IFile file, char[] charContents) {
|
||||||
|
this.file= file;
|
||||||
|
this.charContents= charContents;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @see org.eclipse.jdt.internal.core.index.IDocument#getByteContent()
|
||||||
|
*/
|
||||||
|
public byte[] getByteContent() throws IOException {
|
||||||
|
if (byteContents != null) return byteContents;
|
||||||
|
IPath location = file.getLocation();
|
||||||
|
if (location == null) return new byte[0];
|
||||||
|
return byteContents = org.eclipse.cdt.internal.core.search.Util.getFileByteContent(location.toFile());
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @see org.eclipse.jdt.internal.core.index.IDocument#getCharContent()
|
||||||
|
*/
|
||||||
|
public char[] getCharContent() throws IOException {
|
||||||
|
if (charContents != null) return charContents;
|
||||||
|
IPath location = file.getLocation();
|
||||||
|
if (location == null) return CharOperation.NO_CHAR;
|
||||||
|
return charContents = org.eclipse.cdt.internal.core.search.Util.getFileCharContent(
|
||||||
|
location.toFile(),
|
||||||
|
getEncoding());
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @see org.eclipse.jdt.internal.core.index.IDocument#getEncoding()
|
||||||
|
*/
|
||||||
|
public String getEncoding() {
|
||||||
|
//TODO: Indexer - get encoding
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @see org.eclipse.jdt.internal.core.index.IDocument#getName()
|
||||||
|
*/
|
||||||
|
public String getName() {
|
||||||
|
return file.getFullPath().toString();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @see org.eclipse.jdt.internal.core.index.IDocument#getStringContent()
|
||||||
|
*/
|
||||||
|
public String getStringContent() throws java.io.IOException {
|
||||||
|
return new String(getCharContent());
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @see org.eclipse.jdt.internal.core.index.IDocument#getType()
|
||||||
|
*/
|
||||||
|
public String getType() {
|
||||||
|
String extension= file.getFileExtension();
|
||||||
|
if (extension == null)
|
||||||
|
return ""; //$NON-NLS-1$
|
||||||
|
return extension;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2003 IBM Corporation and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Common Public License v0.5
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/cpl-v05.html
|
||||||
|
******************************************************************************/
|
||||||
|
/*
|
||||||
|
* Created on Jun 1, 2003
|
||||||
|
*/
|
||||||
|
package org.eclipse.cdt.internal.core.index.impl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This interface provides constants used by the search engine.
|
||||||
|
*/
|
||||||
|
public interface IIndexConstants {
|
||||||
|
/**
|
||||||
|
* The signature of the index file.
|
||||||
|
*/
|
||||||
|
public static final String SIGNATURE= "INDEX FILE 0.012"; //$NON-NLS-1$
|
||||||
|
/**
|
||||||
|
* The separator for files in the index file.
|
||||||
|
*/
|
||||||
|
public static final char FILE_SEPARATOR= '/';
|
||||||
|
/**
|
||||||
|
* The size of a block for a <code>Block</code>.
|
||||||
|
*/
|
||||||
|
public static final int BLOCK_SIZE= 8192;
|
||||||
|
}
|
|
@ -0,0 +1,197 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2003 IBM Corporation and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Common Public License v0.5
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/cpl-v05.html
|
||||||
|
******************************************************************************/
|
||||||
|
/*
|
||||||
|
* Created on Jun 1, 2003
|
||||||
|
*/
|
||||||
|
package org.eclipse.cdt.internal.core.index.impl;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.internal.core.index.IDocument;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This index stores the document names in an <code>ObjectVector</code>, and the words in
|
||||||
|
* an <code>HashtableOfObjects</code>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class InMemoryIndex {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hashtable of WordEntrys = words+numbers of the files they appear in.
|
||||||
|
*/
|
||||||
|
protected WordEntryHashedArray words;
|
||||||
|
/**
|
||||||
|
* List of IndexedFiles = file name + a unique number.
|
||||||
|
*/
|
||||||
|
protected IndexedFileHashedArray files;
|
||||||
|
/**
|
||||||
|
* Size of the index.
|
||||||
|
*/
|
||||||
|
protected long footprint;
|
||||||
|
|
||||||
|
private WordEntry[] sortedWordEntries;
|
||||||
|
private IndexedFile[] sortedFiles;
|
||||||
|
public InMemoryIndex() {
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IndexedFile addDocument(IDocument document) {
|
||||||
|
IndexedFile indexedFile= this.files.add(document);
|
||||||
|
this.footprint += indexedFile.footprint() + 4;
|
||||||
|
this.sortedFiles = null;
|
||||||
|
return indexedFile;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Adds the references of the word to the index (reference = number of the file the word belongs to).
|
||||||
|
*/
|
||||||
|
protected void addRef(char[] word, int[] references) {
|
||||||
|
int size= references.length;
|
||||||
|
int i= 0;
|
||||||
|
while (i < size) {
|
||||||
|
if (references[i] != 0)
|
||||||
|
addRef(word, references[i]);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Looks if the word already exists in the index and add the fileNum to this word.
|
||||||
|
* If the word does not exist, it adds it in the index.
|
||||||
|
*/
|
||||||
|
protected void addRef(char[] word, int fileNum) {
|
||||||
|
WordEntry entry= (WordEntry) this.words.get(word);
|
||||||
|
if (entry == null) {
|
||||||
|
entry= new WordEntry(word);
|
||||||
|
entry.addRef(fileNum);
|
||||||
|
this.words.add(entry);
|
||||||
|
this.sortedWordEntries= null;
|
||||||
|
this.footprint += entry.footprint();
|
||||||
|
} else {
|
||||||
|
this.footprint += entry.addRef(fileNum);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addRef(IndexedFile indexedFile, char[] word) {
|
||||||
|
addRef(word, indexedFile.getFileNumber());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addRef(IndexedFile indexedFile, String word) {
|
||||||
|
addRef(word.toCharArray(), indexedFile.getFileNumber());
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Returns the footprint of the index.
|
||||||
|
*/
|
||||||
|
public long getFootprint() {
|
||||||
|
return this.footprint;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Returns the indexed file with the given path, or null if such file does not exist.
|
||||||
|
*/
|
||||||
|
public IndexedFile getIndexedFile(String path) {
|
||||||
|
return files.get(path);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @see IIndex#getNumDocuments()
|
||||||
|
*/
|
||||||
|
public int getNumFiles() {
|
||||||
|
return files.size();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @see IIndex#getNumWords()
|
||||||
|
*/
|
||||||
|
public int getNumWords() {
|
||||||
|
return words.elementSize;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Returns the words contained in the hashtable of words, sorted by alphabetical order.
|
||||||
|
*/
|
||||||
|
protected IndexedFile[] getSortedFiles() {
|
||||||
|
if (this.sortedFiles == null) {
|
||||||
|
IndexedFile[] indexedFiles= files.asArray();
|
||||||
|
Util.sort(indexedFiles);
|
||||||
|
this.sortedFiles= indexedFiles;
|
||||||
|
}
|
||||||
|
return this.sortedFiles;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Returns the word entries contained in the hashtable of words, sorted by alphabetical order.
|
||||||
|
*/
|
||||||
|
protected WordEntry[] getSortedWordEntries() {
|
||||||
|
if (this.sortedWordEntries == null) {
|
||||||
|
WordEntry[] words= this.words.asArray();
|
||||||
|
Util.sort(words);
|
||||||
|
this.sortedWordEntries= words;
|
||||||
|
}
|
||||||
|
return this.sortedWordEntries;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Returns the word entry corresponding to the given word.
|
||||||
|
*/
|
||||||
|
protected WordEntry getWordEntry(char[] word) {
|
||||||
|
return (WordEntry) words.get(word);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Initialises the fields of the index
|
||||||
|
*/
|
||||||
|
public void init() {
|
||||||
|
words= new WordEntryHashedArray(501);
|
||||||
|
files= new IndexedFileHashedArray(101);
|
||||||
|
footprint= 0;
|
||||||
|
sortedWordEntries= null;
|
||||||
|
sortedFiles= null;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Saves the index in the given file.
|
||||||
|
* Structure of the saved Index :
|
||||||
|
* - IndexedFiles in sorted order.
|
||||||
|
* + example:
|
||||||
|
* "c:/com/a.cpp 1"
|
||||||
|
* "c:/com/b.cpp 2"
|
||||||
|
* - References with the words in sorted order
|
||||||
|
* + example:
|
||||||
|
* "classDecl/a 1"
|
||||||
|
* "classDecl/b 2"
|
||||||
|
* "ref/String 1 2"
|
||||||
|
*/
|
||||||
|
public void save(File file) throws IOException {
|
||||||
|
BlocksIndexOutput output= new BlocksIndexOutput(file);
|
||||||
|
save(output);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Saves the index in the given IndexOutput.
|
||||||
|
* Structure of the saved Index :
|
||||||
|
* - IndexedFiles in sorted order.
|
||||||
|
* + example:
|
||||||
|
* "c:/com/a.cpp 1"
|
||||||
|
* "c:/com/b.cpp 2"
|
||||||
|
* - References with the words in sorted order
|
||||||
|
* + example:
|
||||||
|
* "classDecl/a 1"
|
||||||
|
* "classDecl/b 2"
|
||||||
|
* "ref/String 1 2"
|
||||||
|
*/
|
||||||
|
protected void save(IndexOutput output) throws IOException {
|
||||||
|
boolean ok= false;
|
||||||
|
try {
|
||||||
|
output.open();
|
||||||
|
IndexedFile[] indexedFiles= files.asArray();
|
||||||
|
for (int i= 0, length = indexedFiles.length; i < length; ++i)
|
||||||
|
output.addFile(indexedFiles[i]); // written out in order BUT not alphabetical
|
||||||
|
getSortedWordEntries(); // init the slot
|
||||||
|
for (int i= 0, numWords= sortedWordEntries.length; i < numWords; ++i)
|
||||||
|
output.addWord(sortedWordEntries[i]);
|
||||||
|
output.flush();
|
||||||
|
output.close();
|
||||||
|
ok= true;
|
||||||
|
} finally {
|
||||||
|
if (!ok && output != null)
|
||||||
|
output.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,364 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2003 IBM Corporation and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Common Public License v0.5
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/cpl-v05.html
|
||||||
|
******************************************************************************/
|
||||||
|
/*
|
||||||
|
* Created on May 30, 2003
|
||||||
|
*/
|
||||||
|
package org.eclipse.cdt.internal.core.index.impl;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.internal.core.index.IDocument;
|
||||||
|
import org.eclipse.cdt.internal.core.index.IEntryResult;
|
||||||
|
import org.eclipse.cdt.internal.core.index.IIndex;
|
||||||
|
import org.eclipse.cdt.internal.core.index.IIndexer;
|
||||||
|
import org.eclipse.cdt.internal.core.index.IQueryResult;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An Index is used to create an index on the disk, and to make queries. It uses a set of
|
||||||
|
* indexers and a mergeFactory. The index fills an inMemoryIndex up
|
||||||
|
* to it reaches a certain size, and then merges it with a main index on the disk.
|
||||||
|
* <br> <br>
|
||||||
|
* The changes are only taken into account by the queries after a merge.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class Index implements IIndex {
|
||||||
|
/**
|
||||||
|
* Maximum size of the index in memory.
|
||||||
|
*/
|
||||||
|
public static final int MAX_FOOTPRINT= 10000000;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Index in memory, who is merged with mainIndex each times it
|
||||||
|
* reaches a certain size.
|
||||||
|
*/
|
||||||
|
protected InMemoryIndex addsIndex;
|
||||||
|
protected IndexInput addsIndexInput;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* State of the indexGenerator: addsIndex empty <=> MERGED, or
|
||||||
|
* addsIndex not empty <=> CAN_MERGE
|
||||||
|
*/
|
||||||
|
protected int state;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Files removed form the addsIndex.
|
||||||
|
*/
|
||||||
|
protected Map removedInAdds;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Files removed form the oldIndex.
|
||||||
|
*/
|
||||||
|
protected Map removedInOld;
|
||||||
|
protected static final int CAN_MERGE= 0;
|
||||||
|
protected static final int MERGED= 1;
|
||||||
|
private File indexFile;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* String representation of this index.
|
||||||
|
*/
|
||||||
|
public String toString;
|
||||||
|
|
||||||
|
public Index(File indexDirectory, boolean reuseExistingFile) throws IOException {
|
||||||
|
this(indexDirectory,".index", reuseExistingFile); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
|
||||||
|
public Index(File indexDirectory, String indexName, boolean reuseExistingFile) throws IOException {
|
||||||
|
super();
|
||||||
|
state= MERGED;
|
||||||
|
indexFile= new File(indexDirectory, indexName);
|
||||||
|
initialize(reuseExistingFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Index(String indexName, boolean reuseExistingFile) throws IOException {
|
||||||
|
this(indexName, null, reuseExistingFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Index(String indexName, String toString, boolean reuseExistingFile) throws IOException {
|
||||||
|
super();
|
||||||
|
state= MERGED;
|
||||||
|
indexFile= new File(indexName);
|
||||||
|
this.toString = toString;
|
||||||
|
initialize(reuseExistingFile);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Indexes the given document, using the appropriate indexer registered in the indexerRegistry.
|
||||||
|
* If the document already exists in the index, it overrides the previous one. The changes will be
|
||||||
|
* taken into account after a merge.
|
||||||
|
*/
|
||||||
|
public void add(IDocument document, IIndexer indexer) throws IOException {
|
||||||
|
if (timeToMerge()) {
|
||||||
|
merge();
|
||||||
|
}
|
||||||
|
IndexedFile indexedFile= addsIndex.getIndexedFile(document.getName());
|
||||||
|
if (indexedFile != null /*&& removedInAdds.get(document.getName()) == null*/
|
||||||
|
)
|
||||||
|
remove(indexedFile, MergeFactory.ADDS_INDEX);
|
||||||
|
IndexerOutput output= new IndexerOutput(addsIndex);
|
||||||
|
indexer.index(document, output);
|
||||||
|
state= CAN_MERGE;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Returns true if the index in memory is not empty, so
|
||||||
|
* merge() can be called to fill the mainIndex with the files and words
|
||||||
|
* contained in the addsIndex.
|
||||||
|
*/
|
||||||
|
protected boolean canMerge() {
|
||||||
|
return state == CAN_MERGE;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Initialises the indexGenerator.
|
||||||
|
*/
|
||||||
|
public void empty() throws IOException {
|
||||||
|
|
||||||
|
if (indexFile.exists()){
|
||||||
|
indexFile.delete();
|
||||||
|
//initialisation of mainIndex
|
||||||
|
InMemoryIndex mainIndex= new InMemoryIndex();
|
||||||
|
IndexOutput mainIndexOutput= new BlocksIndexOutput(indexFile);
|
||||||
|
if (!indexFile.exists())
|
||||||
|
mainIndex.save(mainIndexOutput);
|
||||||
|
}
|
||||||
|
|
||||||
|
//initialisation of addsIndex
|
||||||
|
addsIndex= new InMemoryIndex();
|
||||||
|
addsIndexInput= new SimpleIndexInput(addsIndex);
|
||||||
|
|
||||||
|
//vectors who keep track of the removed Files
|
||||||
|
removedInAdds= new HashMap(11);
|
||||||
|
removedInOld= new HashMap(11);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @see IIndex#getIndexFile
|
||||||
|
*/
|
||||||
|
public File getIndexFile() {
|
||||||
|
return indexFile;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @see IIndex#getNumDocuments
|
||||||
|
*/
|
||||||
|
public int getNumDocuments() throws IOException {
|
||||||
|
//save();
|
||||||
|
IndexInput input= new BlocksIndexInput(indexFile);
|
||||||
|
try {
|
||||||
|
input.open();
|
||||||
|
return input.getNumFiles();
|
||||||
|
} finally {
|
||||||
|
input.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @see IIndex#getNumWords
|
||||||
|
*/
|
||||||
|
public int getNumWords() throws IOException {
|
||||||
|
//save();
|
||||||
|
IndexInput input= new BlocksIndexInput(indexFile);
|
||||||
|
try {
|
||||||
|
input.open();
|
||||||
|
return input.getNumWords();
|
||||||
|
} finally {
|
||||||
|
input.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Returns the path corresponding to a given document number
|
||||||
|
*/
|
||||||
|
public String getPath(int documentNumber) throws IOException {
|
||||||
|
//save();
|
||||||
|
IndexInput input= new BlocksIndexInput(indexFile);
|
||||||
|
try {
|
||||||
|
input.open();
|
||||||
|
IndexedFile file = input.getIndexedFile(documentNumber);
|
||||||
|
if (file == null) return null;
|
||||||
|
return file.getPath();
|
||||||
|
} finally {
|
||||||
|
input.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* see IIndex.hasChanged
|
||||||
|
*/
|
||||||
|
public boolean hasChanged() {
|
||||||
|
return canMerge();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Initialises the indexGenerator.
|
||||||
|
*/
|
||||||
|
public void initialize(boolean reuseExistingFile) throws IOException {
|
||||||
|
//initialisation of addsIndex
|
||||||
|
addsIndex= new InMemoryIndex();
|
||||||
|
addsIndexInput= new SimpleIndexInput(addsIndex);
|
||||||
|
|
||||||
|
//vectors who keep track of the removed Files
|
||||||
|
removedInAdds= new HashMap(11);
|
||||||
|
removedInOld= new HashMap(11);
|
||||||
|
|
||||||
|
// check whether existing index file can be read
|
||||||
|
if (reuseExistingFile && indexFile.exists()) {
|
||||||
|
IndexInput mainIndexInput= new BlocksIndexInput(indexFile);
|
||||||
|
try {
|
||||||
|
mainIndexInput.open();
|
||||||
|
} catch(IOException e) {
|
||||||
|
BlocksIndexInput input = (BlocksIndexInput)mainIndexInput;
|
||||||
|
try {
|
||||||
|
input.opened = true;
|
||||||
|
input.close();
|
||||||
|
} finally {
|
||||||
|
input.opened = false;
|
||||||
|
}
|
||||||
|
indexFile.delete();
|
||||||
|
mainIndexInput = null;
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
mainIndexInput.close();
|
||||||
|
} else {
|
||||||
|
InMemoryIndex mainIndex= new InMemoryIndex();
|
||||||
|
IndexOutput mainIndexOutput= new BlocksIndexOutput(indexFile);
|
||||||
|
mainIndex.save(mainIndexOutput);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Merges the in memory index and the index on the disk, and saves the results on the disk.
|
||||||
|
*/
|
||||||
|
protected void merge() throws IOException {
|
||||||
|
//initialisation of tempIndex
|
||||||
|
File tempFile= new File(indexFile.getAbsolutePath() + "TempVA"); //$NON-NLS-1$
|
||||||
|
|
||||||
|
IndexInput mainIndexInput= new BlocksIndexInput(indexFile);
|
||||||
|
BlocksIndexOutput tempIndexOutput= new BlocksIndexOutput(tempFile);
|
||||||
|
|
||||||
|
try {
|
||||||
|
//invoke a mergeFactory
|
||||||
|
new MergeFactory(
|
||||||
|
mainIndexInput,
|
||||||
|
addsIndexInput,
|
||||||
|
tempIndexOutput,
|
||||||
|
removedInOld,
|
||||||
|
removedInAdds).merge();
|
||||||
|
|
||||||
|
//rename the file created to become the main index
|
||||||
|
File mainIndexFile= (File) mainIndexInput.getSource();
|
||||||
|
File tempIndexFile= (File) tempIndexOutput.getDestination();
|
||||||
|
mainIndexFile.delete();
|
||||||
|
tempIndexFile.renameTo(mainIndexFile);
|
||||||
|
} finally {
|
||||||
|
//initialise remove vectors and addsindex, and change the state
|
||||||
|
removedInAdds.clear();
|
||||||
|
removedInOld.clear();
|
||||||
|
addsIndex.init();
|
||||||
|
addsIndexInput= new SimpleIndexInput(addsIndex);
|
||||||
|
state= MERGED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @see IIndex#query
|
||||||
|
*/
|
||||||
|
public IQueryResult[] query(String word) throws IOException {
|
||||||
|
//save();
|
||||||
|
IndexInput input= new BlocksIndexInput(indexFile);
|
||||||
|
try {
|
||||||
|
return input.query(word);
|
||||||
|
} finally {
|
||||||
|
input.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public IEntryResult[] queryEntries(char[] prefix) throws IOException {
|
||||||
|
//save();
|
||||||
|
IndexInput input= new BlocksIndexInput(indexFile);
|
||||||
|
try {
|
||||||
|
return input.queryEntriesPrefixedBy(prefix);
|
||||||
|
} finally {
|
||||||
|
input.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @see IIndex#queryInDocumentNames
|
||||||
|
*/
|
||||||
|
public IQueryResult[] queryInDocumentNames(String word) throws IOException {
|
||||||
|
//save();
|
||||||
|
IndexInput input= new BlocksIndexInput(indexFile);
|
||||||
|
try {
|
||||||
|
return input.queryInDocumentNames(word);
|
||||||
|
} finally {
|
||||||
|
input.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @see IIndex#queryPrefix
|
||||||
|
*/
|
||||||
|
public IQueryResult[] queryPrefix(char[] prefix) throws IOException {
|
||||||
|
//save();
|
||||||
|
IndexInput input= new BlocksIndexInput(indexFile);
|
||||||
|
try {
|
||||||
|
return input.queryFilesReferringToPrefix(prefix);
|
||||||
|
} finally {
|
||||||
|
input.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @see IIndex#remove
|
||||||
|
*/
|
||||||
|
public void remove(String documentName) throws IOException {
|
||||||
|
IndexedFile file= addsIndex.getIndexedFile(documentName);
|
||||||
|
if (file != null) {
|
||||||
|
//the file is in the adds Index, we remove it from this one
|
||||||
|
Int lastRemoved= (Int) removedInAdds.get(documentName);
|
||||||
|
if (lastRemoved != null) {
|
||||||
|
int fileNum= file.getFileNumber();
|
||||||
|
if (lastRemoved.value < fileNum)
|
||||||
|
lastRemoved.value= fileNum;
|
||||||
|
} else
|
||||||
|
removedInAdds.put(documentName, new Int(file.getFileNumber()));
|
||||||
|
} else {
|
||||||
|
//we remove the file from the old index
|
||||||
|
removedInOld.put(documentName, new Int(1));
|
||||||
|
}
|
||||||
|
state= CAN_MERGE;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Removes the given document from the given index (MergeFactory.ADDS_INDEX for the
|
||||||
|
* in memory index, MergeFactory.OLD_INDEX for the index on the disk).
|
||||||
|
*/
|
||||||
|
protected void remove(IndexedFile file, int index) throws IOException {
|
||||||
|
String name= file.getPath();
|
||||||
|
if (index == MergeFactory.ADDS_INDEX) {
|
||||||
|
Int lastRemoved= (Int) removedInAdds.get(name);
|
||||||
|
if (lastRemoved != null) {
|
||||||
|
if (lastRemoved.value < file.getFileNumber())
|
||||||
|
lastRemoved.value= file.getFileNumber();
|
||||||
|
} else
|
||||||
|
removedInAdds.put(name, new Int(file.getFileNumber()));
|
||||||
|
} else if (index == MergeFactory.OLD_INDEX)
|
||||||
|
removedInOld.put(name, new Int(1));
|
||||||
|
else
|
||||||
|
throw new Error();
|
||||||
|
state= CAN_MERGE;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @see IIndex#save
|
||||||
|
*/
|
||||||
|
public void save() throws IOException {
|
||||||
|
if (canMerge())
|
||||||
|
merge();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Returns true if the in memory index reaches a critical size,
|
||||||
|
* to merge it with the index on the disk.
|
||||||
|
*/
|
||||||
|
protected boolean timeToMerge() {
|
||||||
|
return (addsIndex.getFootprint() >= MAX_FOOTPRINT);
|
||||||
|
}
|
||||||
|
public String toString() {
|
||||||
|
String str = this.toString;
|
||||||
|
if (str == null) str = super.toString();
|
||||||
|
str += "(length: "+ getIndexFile().length() +")"; //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,74 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2003 IBM Corporation and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Common Public License v0.5
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/cpl-v05.html
|
||||||
|
******************************************************************************/
|
||||||
|
/*
|
||||||
|
* Created on Jun 1, 2003
|
||||||
|
*/
|
||||||
|
package org.eclipse.cdt.internal.core.index.impl;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.internal.core.search.CharOperation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An indexBlock stores wordEntries.
|
||||||
|
*/
|
||||||
|
public abstract class IndexBlock extends Block {
|
||||||
|
|
||||||
|
public IndexBlock(int blockSize) {
|
||||||
|
super(blockSize);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Adds the given wordEntry to the indexBlock.
|
||||||
|
*/
|
||||||
|
public abstract boolean addEntry(WordEntry entry);
|
||||||
|
/**
|
||||||
|
* @see Block#clear()
|
||||||
|
*/
|
||||||
|
public void clear() {
|
||||||
|
reset();
|
||||||
|
super.clear();
|
||||||
|
}
|
||||||
|
public WordEntry findEntryMatching(char[] pattern, boolean isCaseSensitive) {
|
||||||
|
reset();
|
||||||
|
WordEntry entry= new WordEntry();
|
||||||
|
while (nextEntry(entry)) {
|
||||||
|
if (CharOperation.match(pattern, entry.getWord(), isCaseSensitive)) {
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
public WordEntry findEntryPrefixedBy(char[] word, boolean isCaseSensitive) {
|
||||||
|
reset();
|
||||||
|
WordEntry entry= new WordEntry();
|
||||||
|
while (nextEntry(entry)) {
|
||||||
|
if (CharOperation.prefixEquals(entry.getWord(), word, isCaseSensitive)) {
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
public WordEntry findExactEntry(char[] word) {
|
||||||
|
reset();
|
||||||
|
WordEntry entry= new WordEntry();
|
||||||
|
while (nextEntry(entry)) {
|
||||||
|
if (CharOperation.equals(entry.getWord(), word)) {
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Returns whether the block is empty or not (if it doesn't contain any wordEntry).
|
||||||
|
*/
|
||||||
|
public abstract boolean isEmpty();
|
||||||
|
/**
|
||||||
|
* Finds the next wordEntry and stores it in the given entry.
|
||||||
|
*/
|
||||||
|
public abstract boolean nextEntry(WordEntry entry);
|
||||||
|
public void reset() {
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,131 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2003 IBM Corporation and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Common Public License v0.5
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/cpl-v05.html
|
||||||
|
******************************************************************************/
|
||||||
|
/*
|
||||||
|
* Created on Jun 1, 2003
|
||||||
|
*/
|
||||||
|
package org.eclipse.cdt.internal.core.index.impl;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import org.eclipse.cdt.internal.core.index.IDocument;
|
||||||
|
import org.eclipse.cdt.internal.core.index.IEntryResult;
|
||||||
|
import org.eclipse.cdt.internal.core.index.IQueryResult;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class provides an input on an index, after it has been generated.
|
||||||
|
* You can access all the files of an index via getNextFile(), getCurrentFile()
|
||||||
|
* and moveToNextFile() (idem for the word entries).
|
||||||
|
* The usage is the same for every subclass: creation (constructor), opening
|
||||||
|
* (the open() method), usage, and closing (the close() method), to release the
|
||||||
|
* data source used by this input.
|
||||||
|
*/
|
||||||
|
public abstract class IndexInput {
|
||||||
|
protected int filePosition;
|
||||||
|
protected WordEntry currentWordEntry;
|
||||||
|
protected int wordPosition;
|
||||||
|
|
||||||
|
|
||||||
|
public IndexInput() {
|
||||||
|
super();
|
||||||
|
wordPosition= 1;
|
||||||
|
filePosition= 1;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* clears the cache of this indexInput, if it keeps track of the information already read.
|
||||||
|
*/
|
||||||
|
public abstract void clearCache();
|
||||||
|
/**
|
||||||
|
* Closes the IndexInput. For example, if the input is on a RandomAccessFile,
|
||||||
|
* it calls the close() method of RandomAccessFile.
|
||||||
|
*/
|
||||||
|
public abstract void close() throws IOException;
|
||||||
|
/**
|
||||||
|
* Returns the current file the indexInput is pointing to in the index.
|
||||||
|
*/
|
||||||
|
public abstract IndexedFile getCurrentFile() throws IOException;
|
||||||
|
/**
|
||||||
|
* Returns the current file the indexInput is pointing to in the index.
|
||||||
|
*/
|
||||||
|
public WordEntry getCurrentWordEntry() throws IOException {
|
||||||
|
if (!hasMoreWords())
|
||||||
|
return null;
|
||||||
|
return currentWordEntry;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Returns the position of the current file the input is pointing to in the index.
|
||||||
|
*/
|
||||||
|
public int getFilePosition() {
|
||||||
|
return filePosition;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Returns the indexedFile corresponding to the given document number in the index the input
|
||||||
|
* reads in, or null if such indexedFile does not exist.
|
||||||
|
*/
|
||||||
|
public abstract IndexedFile getIndexedFile(int fileNum) throws IOException;
|
||||||
|
/**
|
||||||
|
* Returns the indexedFile corresponding to the given document in the index the input
|
||||||
|
* reads in (e.g. the indexedFile with the same path in this index), or null if such
|
||||||
|
* indexedFile does not exist.
|
||||||
|
*/
|
||||||
|
public abstract IndexedFile getIndexedFile(IDocument document) throws IOException;
|
||||||
|
/**
|
||||||
|
* Returns the number of files in the index.
|
||||||
|
*/
|
||||||
|
public abstract int getNumFiles();
|
||||||
|
/**
|
||||||
|
* Returns the number of unique words in the index.
|
||||||
|
*/
|
||||||
|
public abstract int getNumWords();
|
||||||
|
/**
|
||||||
|
* Returns the Object the input is reading from. It can be an IIndex,
|
||||||
|
* a File, ...
|
||||||
|
*/
|
||||||
|
public abstract Object getSource();
|
||||||
|
/**
|
||||||
|
* Returns true if the input has not reached the end of the index for the files.
|
||||||
|
*/
|
||||||
|
public boolean hasMoreFiles() {
|
||||||
|
return getFilePosition() <= getNumFiles();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Returns true if the input has not reached the end of the index for the files.
|
||||||
|
*/
|
||||||
|
public boolean hasMoreWords() {
|
||||||
|
return wordPosition <= getNumWords();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Moves the pointer on the current file to the next file in the index.
|
||||||
|
*/
|
||||||
|
public abstract void moveToNextFile() throws IOException;
|
||||||
|
/**
|
||||||
|
* Moves the pointer on the current word to the next file in the index.
|
||||||
|
*/
|
||||||
|
public abstract void moveToNextWordEntry() throws IOException;
|
||||||
|
/**
|
||||||
|
* Open the Source where the input gets the information from.
|
||||||
|
*/
|
||||||
|
public abstract void open() throws IOException;
|
||||||
|
/**
|
||||||
|
* Returns the list of the files containing the given word in the index.
|
||||||
|
*/
|
||||||
|
public abstract IQueryResult[] query(String word) throws IOException;
|
||||||
|
public abstract IEntryResult[] queryEntriesPrefixedBy(char[] prefix) throws IOException;
|
||||||
|
public abstract IQueryResult[] queryFilesReferringToPrefix(char[] prefix) throws IOException;
|
||||||
|
/**
|
||||||
|
* Returns the list of the files whose name contain the given word in the index.
|
||||||
|
*/
|
||||||
|
public abstract IQueryResult[] queryInDocumentNames(String word) throws IOException;
|
||||||
|
/**
|
||||||
|
* Set the pointer on the current file to the first file of the index.
|
||||||
|
*/
|
||||||
|
protected abstract void setFirstFile() throws IOException;
|
||||||
|
/**
|
||||||
|
* Set the pointer on the current word to the first word of the index.
|
||||||
|
*/
|
||||||
|
protected abstract void setFirstWord() throws IOException;
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2003 IBM Corporation and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Common Public License v0.5
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/cpl-v05.html
|
||||||
|
******************************************************************************/
|
||||||
|
/*
|
||||||
|
* Created on Jun 1, 2003
|
||||||
|
*/
|
||||||
|
package org.eclipse.cdt.internal.core.index.impl;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An indexOutput is used to write an index into a different object (a File, ...).
|
||||||
|
*/
|
||||||
|
public abstract class IndexOutput {
|
||||||
|
/**
|
||||||
|
* Adds a File to the destination.
|
||||||
|
*/
|
||||||
|
public abstract void addFile(IndexedFile file) throws IOException;
|
||||||
|
/**
|
||||||
|
* Adds a word to the destination.
|
||||||
|
*/
|
||||||
|
public abstract void addWord(WordEntry word) throws IOException;
|
||||||
|
/**
|
||||||
|
* Closes the output, releasing the resources it was using.
|
||||||
|
*/
|
||||||
|
public abstract void close() throws IOException;
|
||||||
|
/**
|
||||||
|
* Flushes the output.
|
||||||
|
*/
|
||||||
|
public abstract void flush() throws IOException;
|
||||||
|
/**
|
||||||
|
* Returns the Object the output is writing to. It can be a file, another type of index, ...
|
||||||
|
*/
|
||||||
|
public abstract Object getDestination();
|
||||||
|
/**
|
||||||
|
* Opens the output, before writing any information.
|
||||||
|
*/
|
||||||
|
public abstract void open() throws IOException;
|
||||||
|
}
|
|
@ -0,0 +1,315 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2003 IBM Corporation and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Common Public License v0.5
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/cpl-v05.html
|
||||||
|
******************************************************************************/
|
||||||
|
/*
|
||||||
|
* Created on Jun 1, 2003
|
||||||
|
*/
|
||||||
|
package org.eclipse.cdt.internal.core.index.impl;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.RandomAccessFile;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.internal.core.search.CharOperation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An indexSummary is used when saving an index into a BlocksIndexOuput or
|
||||||
|
* reading it from a BlocksIndexInput. It contains basic informations about
|
||||||
|
* an index: first files/words in each block, number of files/words.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class IndexSummary {
|
||||||
|
/**
|
||||||
|
* First file for each block.
|
||||||
|
*/
|
||||||
|
protected ArrayList firstFilesInBlocks= new ArrayList();
|
||||||
|
/**
|
||||||
|
* First word for each block.
|
||||||
|
*/
|
||||||
|
protected ArrayList firstWordsInBlocks= new ArrayList();
|
||||||
|
/**
|
||||||
|
* Number of files in the index.
|
||||||
|
*/
|
||||||
|
protected int numFiles;
|
||||||
|
/**
|
||||||
|
* Number of words in the index.
|
||||||
|
*/
|
||||||
|
protected int numWords;
|
||||||
|
|
||||||
|
static class FirstFileInBlock {
|
||||||
|
IndexedFile indexedFile;
|
||||||
|
int blockNum;
|
||||||
|
}
|
||||||
|
|
||||||
|
static class FirstWordInBlock {
|
||||||
|
char[] word;
|
||||||
|
int blockNum;
|
||||||
|
public String toString(){
|
||||||
|
return "FirstWordInBlock: " + new String(word) + ", blockNum: " + blockNum; //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int firstWordBlockNum;
|
||||||
|
protected boolean firstWordAdded= true;
|
||||||
|
/**
|
||||||
|
* Adds the given file as the first file for the given Block number.
|
||||||
|
*/
|
||||||
|
public void addFirstFileInBlock(IndexedFile indexedFile, int blockNum) {
|
||||||
|
FirstFileInBlock entry= new FirstFileInBlock();
|
||||||
|
entry.indexedFile= indexedFile;
|
||||||
|
entry.blockNum= blockNum;
|
||||||
|
firstFilesInBlocks.add(entry);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Adds the given word as the first word for the given Block number.
|
||||||
|
*/
|
||||||
|
public void addFirstWordInBlock(char[] word, int blockNum) {
|
||||||
|
if (firstWordAdded) {
|
||||||
|
firstWordBlockNum= blockNum;
|
||||||
|
firstWordAdded= false;
|
||||||
|
}
|
||||||
|
FirstWordInBlock entry= new FirstWordInBlock();
|
||||||
|
entry.word= word;
|
||||||
|
entry.blockNum= blockNum;
|
||||||
|
firstWordsInBlocks.add(entry);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Returns the numbers of all the blocks
|
||||||
|
*/
|
||||||
|
public int[] getAllBlockNums() {
|
||||||
|
|
||||||
|
int max = firstWordsInBlocks.size();
|
||||||
|
int[] blockNums = new int[max];
|
||||||
|
for (int i = 0; i < max; i++){
|
||||||
|
blockNums[i] = ((FirstWordInBlock)firstWordsInBlocks.get(i)).blockNum;
|
||||||
|
}
|
||||||
|
return blockNums;
|
||||||
|
}
|
||||||
|
public int getBlockNum(int blockLocation) {
|
||||||
|
return ((FirstWordInBlock) firstWordsInBlocks.get(blockLocation)).blockNum;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Returns the number of the Block containing the file with the given number.
|
||||||
|
*/
|
||||||
|
public int getBlockNumForFileNum(int fileNum) {
|
||||||
|
int min= 0;
|
||||||
|
int max= firstFilesInBlocks.size() - 1;
|
||||||
|
while (min <= max) {
|
||||||
|
int mid= (min + max) / 2;
|
||||||
|
FirstFileInBlock entry= (FirstFileInBlock) firstFilesInBlocks.get(mid);
|
||||||
|
int compare= fileNum - entry.indexedFile.getFileNumber();
|
||||||
|
if (compare == 0)
|
||||||
|
return entry.blockNum;
|
||||||
|
if (compare < 0)
|
||||||
|
max= mid - 1;
|
||||||
|
else
|
||||||
|
min= mid + 1;
|
||||||
|
}
|
||||||
|
if (max < 0)
|
||||||
|
return -1;
|
||||||
|
FirstFileInBlock entry= (FirstFileInBlock) firstFilesInBlocks.get(max);
|
||||||
|
return entry.blockNum;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Returns the number of the Block containing the given word.
|
||||||
|
*/
|
||||||
|
public int getBlockNumForWord(char[] word) {
|
||||||
|
int min= 0;
|
||||||
|
int max= firstWordsInBlocks.size() - 1;
|
||||||
|
while (min <= max) {
|
||||||
|
int mid= (min + max) / 2;
|
||||||
|
FirstWordInBlock entry= (FirstWordInBlock) firstWordsInBlocks.get(mid);
|
||||||
|
int compare= Util.compare(word, entry.word);
|
||||||
|
if (compare == 0)
|
||||||
|
return entry.blockNum;
|
||||||
|
if (compare < 0)
|
||||||
|
max= mid - 1;
|
||||||
|
else
|
||||||
|
min= mid + 1;
|
||||||
|
}
|
||||||
|
if (max < 0)
|
||||||
|
return -1;
|
||||||
|
FirstWordInBlock entry= (FirstWordInBlock) firstWordsInBlocks.get(max);
|
||||||
|
return entry.blockNum;
|
||||||
|
}
|
||||||
|
public int[] getBlockNumsForPrefix(char[] prefix) {
|
||||||
|
int min= 0;
|
||||||
|
int size= firstWordsInBlocks.size();
|
||||||
|
int max= size - 1;
|
||||||
|
int match= -1;
|
||||||
|
while (min <= max && match < 0) {
|
||||||
|
int mid= (min + max) / 2;
|
||||||
|
FirstWordInBlock entry= (FirstWordInBlock) firstWordsInBlocks.get(mid);
|
||||||
|
int compare= CharOperation.compareWith(entry.word, prefix);
|
||||||
|
if (compare == 0) {
|
||||||
|
match= mid;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (compare >= 0)
|
||||||
|
max= mid - 1;
|
||||||
|
else
|
||||||
|
min= mid + 1;
|
||||||
|
}
|
||||||
|
if (max < 0)
|
||||||
|
return new int[0];
|
||||||
|
|
||||||
|
if (match < 0)
|
||||||
|
match= max;
|
||||||
|
|
||||||
|
int firstBlock= match - 1;
|
||||||
|
// Look if previous blocks are affected
|
||||||
|
for (; firstBlock >= 0; firstBlock--) {
|
||||||
|
FirstWordInBlock entry= (FirstWordInBlock) firstWordsInBlocks.get(firstBlock);
|
||||||
|
if (!CharOperation.prefixEquals(prefix, entry.word))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (firstBlock < 0)
|
||||||
|
firstBlock= 0;
|
||||||
|
|
||||||
|
// Look if next blocks are affected
|
||||||
|
int firstNotIncludedBlock= match + 1;
|
||||||
|
for (; firstNotIncludedBlock < size; firstNotIncludedBlock++) {
|
||||||
|
FirstWordInBlock entry= (FirstWordInBlock) firstWordsInBlocks.get(firstNotIncludedBlock);
|
||||||
|
if (!CharOperation.prefixEquals(prefix, entry.word))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
int numberOfBlocks= firstNotIncludedBlock - firstBlock;
|
||||||
|
int[] result= new int[numberOfBlocks];
|
||||||
|
int pos= firstBlock;
|
||||||
|
for (int i= 0; i < numberOfBlocks; i++, pos++) {
|
||||||
|
FirstWordInBlock entry= (FirstWordInBlock) firstWordsInBlocks.get(pos);
|
||||||
|
result[i]= entry.blockNum;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
public int getFirstBlockLocationForPrefix(char[] prefix) {
|
||||||
|
int min = 0;
|
||||||
|
int size = firstWordsInBlocks.size();
|
||||||
|
int max = size - 1;
|
||||||
|
int match = -1;
|
||||||
|
while (min <= max) {
|
||||||
|
int mid = (min + max) / 2;
|
||||||
|
FirstWordInBlock entry = (FirstWordInBlock) firstWordsInBlocks.get(mid);
|
||||||
|
int compare = CharOperation.compareWith(entry.word, prefix);
|
||||||
|
if (compare == 0) {
|
||||||
|
match = mid;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (compare >= 0) {
|
||||||
|
max = mid - 1;
|
||||||
|
} else {
|
||||||
|
match = mid; // not perfect match, but could be inside
|
||||||
|
min = mid + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (max < 0) return -1;
|
||||||
|
|
||||||
|
// no match at all, might be some matching entries inside max block
|
||||||
|
if (match < 0){
|
||||||
|
match = max;
|
||||||
|
} else {
|
||||||
|
// look for possible matches inside previous blocks
|
||||||
|
while (match > 0){
|
||||||
|
FirstWordInBlock entry = (FirstWordInBlock) firstWordsInBlocks.get(match);
|
||||||
|
if (!CharOperation.prefixEquals(prefix, entry.word))
|
||||||
|
break;
|
||||||
|
match--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return match;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Returns the number of the first IndexBlock (containing words).
|
||||||
|
*/
|
||||||
|
public int getFirstWordBlockNum() {
|
||||||
|
return firstWordBlockNum;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Blocks are contiguous, so the next one is a potential candidate if its first word starts with
|
||||||
|
* the given prefix
|
||||||
|
*/
|
||||||
|
public int getNextBlockLocationForPrefix(char[] prefix, int blockLoc) {
|
||||||
|
if (++blockLoc < firstWordsInBlocks.size()){
|
||||||
|
FirstWordInBlock entry= (FirstWordInBlock) firstWordsInBlocks.get(blockLoc);
|
||||||
|
if (CharOperation.prefixEquals(prefix, entry.word)) return blockLoc;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Returns the number of files contained in the index.
|
||||||
|
*/
|
||||||
|
public int getNumFiles() {
|
||||||
|
return numFiles;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Returns the number of words contained in the index.
|
||||||
|
*/
|
||||||
|
public int getNumWords() {
|
||||||
|
return numWords;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Loads the summary in memory.
|
||||||
|
*/
|
||||||
|
public void read(RandomAccessFile raf) throws IOException {
|
||||||
|
numFiles= raf.readInt();
|
||||||
|
numWords= raf.readInt();
|
||||||
|
firstWordBlockNum= raf.readInt();
|
||||||
|
int numFirstFiles= raf.readInt();
|
||||||
|
for (int i= 0; i < numFirstFiles; ++i) {
|
||||||
|
FirstFileInBlock entry= new FirstFileInBlock();
|
||||||
|
String path= raf.readUTF();
|
||||||
|
int fileNum= raf.readInt();
|
||||||
|
entry.indexedFile= new IndexedFile(path, fileNum);
|
||||||
|
entry.blockNum= raf.readInt();
|
||||||
|
firstFilesInBlocks.add(entry);
|
||||||
|
}
|
||||||
|
int numFirstWords= raf.readInt();
|
||||||
|
for (int i= 0; i < numFirstWords; ++i) {
|
||||||
|
FirstWordInBlock entry= new FirstWordInBlock();
|
||||||
|
entry.word= raf.readUTF().toCharArray();
|
||||||
|
entry.blockNum= raf.readInt();
|
||||||
|
firstWordsInBlocks.add(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Sets the number of files of the index.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public void setNumFiles(int numFiles) {
|
||||||
|
this.numFiles= numFiles;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Sets the number of words of the index.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public void setNumWords(int numWords) {
|
||||||
|
this.numWords= numWords;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Saves the summary on the disk.
|
||||||
|
*/
|
||||||
|
public void write(RandomAccessFile raf) throws IOException {
|
||||||
|
raf.writeInt(numFiles);
|
||||||
|
raf.writeInt(numWords);
|
||||||
|
raf.writeInt(firstWordBlockNum);
|
||||||
|
raf.writeInt(firstFilesInBlocks.size());
|
||||||
|
for (int i= 0, size= firstFilesInBlocks.size(); i < size; ++i) {
|
||||||
|
FirstFileInBlock entry= (FirstFileInBlock) firstFilesInBlocks.get(i);
|
||||||
|
raf.writeUTF(entry.indexedFile.getPath());
|
||||||
|
raf.writeInt(entry.indexedFile.getFileNumber());
|
||||||
|
raf.writeInt(entry.blockNum);
|
||||||
|
}
|
||||||
|
raf.writeInt(firstWordsInBlocks.size());
|
||||||
|
for (int i= 0, size= firstWordsInBlocks.size(); i < size; ++i) {
|
||||||
|
FirstWordInBlock entry= (FirstWordInBlock) firstWordsInBlocks.get(i);
|
||||||
|
raf.writeUTF(new String(entry.word));
|
||||||
|
raf.writeInt(entry.blockNum);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2003 IBM Corporation and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Common Public License v0.5
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/cpl-v05.html
|
||||||
|
******************************************************************************/
|
||||||
|
/*
|
||||||
|
* Created on Jun 1, 2003
|
||||||
|
*/
|
||||||
|
package org.eclipse.cdt.internal.core.index.impl;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.internal.core.index.IQueryResult;
|
||||||
|
import org.eclipse.cdt.internal.core.index.IDocument;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An indexedFile associates a number to a document path, and document properties.
|
||||||
|
* It is what we add into an index, and the result of a query.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class IndexedFile implements IQueryResult {
|
||||||
|
protected String path;
|
||||||
|
protected int fileNumber;
|
||||||
|
|
||||||
|
public IndexedFile(String path, int fileNum) {
|
||||||
|
if (fileNum < 1)
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
this.fileNumber= fileNum;
|
||||||
|
this.path= path;
|
||||||
|
}
|
||||||
|
public IndexedFile(IDocument document, int fileNum) {
|
||||||
|
if (fileNum < 1)
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
this.path= document.getName();
|
||||||
|
this.fileNumber= fileNum;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Returns the size of the indexedFile.
|
||||||
|
*/
|
||||||
|
public int footprint() {
|
||||||
|
//object+ 2 slots + size of the string (header + 4 slots + char[])
|
||||||
|
return 8 + (2 * 4) + (8 + (4 * 4) + 8 + path.length() * 2);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Returns the file number.
|
||||||
|
*/
|
||||||
|
public int getFileNumber() {
|
||||||
|
return fileNumber;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Returns the path.
|
||||||
|
*/
|
||||||
|
public String getPath() {
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Sets the file number.
|
||||||
|
*/
|
||||||
|
public void setFileNumber(int fileNumber) {
|
||||||
|
this.fileNumber= fileNumber;
|
||||||
|
}
|
||||||
|
public String toString() {
|
||||||
|
return "IndexedFile(" + fileNumber + ": " + path + ")"; //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-3$
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,109 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2003 IBM Corporation and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Common Public License v0.5
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/cpl-v05.html
|
||||||
|
******************************************************************************/
|
||||||
|
/*
|
||||||
|
* Created on Jun 1, 2003
|
||||||
|
*/
|
||||||
|
package org.eclipse.cdt.internal.core.index.impl;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.internal.core.index.IDocument;
|
||||||
|
|
||||||
|
public final class IndexedFileHashedArray {
|
||||||
|
|
||||||
|
private IndexedFile elements[];
|
||||||
|
private int elementSize; // number of elements in the table
|
||||||
|
private int threshold;
|
||||||
|
private int lastId;
|
||||||
|
private ArrayList replacedElements;
|
||||||
|
|
||||||
|
public IndexedFileHashedArray(int size) {
|
||||||
|
if (size < 7) size = 7;
|
||||||
|
this.elements = new IndexedFile[2 * size + 1];
|
||||||
|
this.elementSize = 0;
|
||||||
|
this.threshold = size + 1; // size is the expected number of elements
|
||||||
|
this.lastId = 0;
|
||||||
|
this.replacedElements = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IndexedFile add(IDocument document) {
|
||||||
|
return add(new IndexedFile(document, ++lastId));
|
||||||
|
}
|
||||||
|
|
||||||
|
private IndexedFile add(IndexedFile file) {
|
||||||
|
int length = elements.length;
|
||||||
|
String path = file.getPath();
|
||||||
|
int index = (path.hashCode() & 0x7FFFFFFF) % length;
|
||||||
|
IndexedFile current;
|
||||||
|
while ((current = elements[index]) != null) {
|
||||||
|
if (current.getPath().equals(path)) {
|
||||||
|
if (replacedElements == null) replacedElements = new ArrayList(5);
|
||||||
|
replacedElements.add(current);
|
||||||
|
return elements[index] = file;
|
||||||
|
}
|
||||||
|
if (++index == length) index = 0;
|
||||||
|
}
|
||||||
|
elements[index] = file;
|
||||||
|
|
||||||
|
// assumes the threshold is never equal to the size of the table
|
||||||
|
if (++elementSize > threshold) grow();
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IndexedFile[] asArray() {
|
||||||
|
IndexedFile[] array = new IndexedFile[lastId];
|
||||||
|
for (int i = 0, length = elements.length; i < length; i++) {
|
||||||
|
IndexedFile current = elements[i];
|
||||||
|
if (current != null)
|
||||||
|
array[current.fileNumber - 1] = current;
|
||||||
|
}
|
||||||
|
if (replacedElements != null) {
|
||||||
|
for (int i = 0, length = replacedElements.size(); i < length; i++) {
|
||||||
|
IndexedFile current = (IndexedFile) replacedElements.get(i);
|
||||||
|
array[current.fileNumber - 1] = current;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IndexedFile get(String path) {
|
||||||
|
int length = elements.length;
|
||||||
|
int index = (path.hashCode() & 0x7FFFFFFF) % length;
|
||||||
|
IndexedFile current;
|
||||||
|
while ((current = elements[index]) != null) {
|
||||||
|
if (current.getPath().equals(path)) return current;
|
||||||
|
if (++index == length) index = 0;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void grow() {
|
||||||
|
IndexedFileHashedArray newArray = new IndexedFileHashedArray(elementSize * 2); // double the number of expected elements
|
||||||
|
for (int i = 0, length = elements.length; i < length; i++)
|
||||||
|
if (elements[i] != null)
|
||||||
|
newArray.add(elements[i]);
|
||||||
|
|
||||||
|
// leave replacedElements as is
|
||||||
|
this.elements = newArray.elements;
|
||||||
|
this.elementSize = newArray.elementSize;
|
||||||
|
this.threshold = newArray.threshold;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int size() {
|
||||||
|
return elementSize + (replacedElements == null ? 0 : replacedElements.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
String s = ""; //$NON-NLS-1$
|
||||||
|
IndexedFile[] files = asArray();
|
||||||
|
for (int i = 0, length = files.length; i < length; i++)
|
||||||
|
s += files[i].toString() + "\n"; //$NON-NLS-1$
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2003 IBM Corporation and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Common Public License v0.5
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/cpl-v05.html
|
||||||
|
******************************************************************************/
|
||||||
|
/*
|
||||||
|
* Created on Jun 1, 2003
|
||||||
|
*/
|
||||||
|
package org.eclipse.cdt.internal.core.index.impl;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.internal.core.index.IIndexerOutput;
|
||||||
|
import org.eclipse.cdt.internal.core.index.IDocument;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An indexerOutput is used by an indexer to add documents and word references to
|
||||||
|
* an inMemoryIndex. It keeps track of the document being indexed and add the
|
||||||
|
* word references to this document (so you do not need to precise the document
|
||||||
|
* each time you add a word).
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class IndexerOutput implements IIndexerOutput {
|
||||||
|
protected InMemoryIndex index;
|
||||||
|
protected IndexedFile indexedFile;
|
||||||
|
protected IDocument document;
|
||||||
|
/**
|
||||||
|
* IndexerOutput constructor comment.
|
||||||
|
*/
|
||||||
|
public IndexerOutput(InMemoryIndex index) {
|
||||||
|
this.index= index;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Adds the given document to the inMemoryIndex.
|
||||||
|
*/
|
||||||
|
public void addDocument(IDocument document) {
|
||||||
|
if (indexedFile == null) {
|
||||||
|
indexedFile= index.addDocument(document);
|
||||||
|
} else {
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Adds a reference to the given word to the inMemoryIndex.
|
||||||
|
*/
|
||||||
|
public void addRef(char[] word) {
|
||||||
|
if (indexedFile == null) {
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
index.addRef(indexedFile, word);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Adds a reference to the given word to the inMemoryIndex.
|
||||||
|
*/
|
||||||
|
public void addRef(String word) {
|
||||||
|
addRef(word.toCharArray());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2003 IBM Corporation and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Common Public License v0.5
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/cpl-v05.html
|
||||||
|
******************************************************************************/
|
||||||
|
/*
|
||||||
|
* Created on Jun 1, 2003
|
||||||
|
*/
|
||||||
|
package org.eclipse.cdt.internal.core.index.impl;
|
||||||
|
|
||||||
|
public class Int {
|
||||||
|
public int value;
|
||||||
|
/**
|
||||||
|
* Int constructor comment.
|
||||||
|
*/
|
||||||
|
public Int(int i) {
|
||||||
|
value= i;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,225 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2003 IBM Corporation and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Common Public License v0.5
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/cpl-v05.html
|
||||||
|
******************************************************************************/
|
||||||
|
/*
|
||||||
|
* Created on Jun 1, 2003
|
||||||
|
*/
|
||||||
|
package org.eclipse.cdt.internal.core.index.impl;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A mergeFactory is used to merge 2 indexes into one. One of the indexes
|
||||||
|
* (oldIndex) is on the disk and the other(addsIndex) is in memory.
|
||||||
|
* The merge respects the following rules: <br>
|
||||||
|
* - The files are sorted in alphabetical order;<br>
|
||||||
|
* - if a file is in oldIndex and addsIndex, the one which is added
|
||||||
|
* is the one in the addsIndex.<br>
|
||||||
|
*/
|
||||||
|
public class MergeFactory {
|
||||||
|
/**
|
||||||
|
* Input on the addsIndex.
|
||||||
|
*/
|
||||||
|
protected IndexInput addsInput;
|
||||||
|
/**
|
||||||
|
* Input on the oldIndex.
|
||||||
|
*/
|
||||||
|
protected IndexInput oldInput;
|
||||||
|
/**
|
||||||
|
* Output to write the result of the merge in.
|
||||||
|
*/
|
||||||
|
protected BlocksIndexOutput mergeOutput;
|
||||||
|
/**
|
||||||
|
* Files removed from oldIndex.
|
||||||
|
*/
|
||||||
|
protected Map removedInOld;
|
||||||
|
/**
|
||||||
|
* Files removed from addsIndex.
|
||||||
|
*/
|
||||||
|
protected Map removedInAdds;
|
||||||
|
protected int[] mappingOld;
|
||||||
|
protected int[] mappingAdds;
|
||||||
|
public static final int ADDS_INDEX= 0;
|
||||||
|
public static final int OLD_INDEX= 1;
|
||||||
|
/**
|
||||||
|
* MergeFactory constructor comment.
|
||||||
|
* @param directory java.io.File
|
||||||
|
*/
|
||||||
|
public MergeFactory(IndexInput oldIndexInput, IndexInput addsIndexInput, BlocksIndexOutput mergeIndexOutput, Map removedInOld, Map removedInAdds) {
|
||||||
|
oldInput= oldIndexInput;
|
||||||
|
addsInput= addsIndexInput;
|
||||||
|
mergeOutput= mergeIndexOutput;
|
||||||
|
this.removedInOld= removedInOld;
|
||||||
|
this.removedInAdds= removedInAdds;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Initialise the merge.
|
||||||
|
*/
|
||||||
|
protected void init() {
|
||||||
|
mappingOld= new int[oldInput.getNumFiles() + 1];
|
||||||
|
mappingAdds= new int[addsInput.getNumFiles() + 1];
|
||||||
|
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Merges the 2 indexes into a new one on the disk.
|
||||||
|
*/
|
||||||
|
public void merge() throws IOException {
|
||||||
|
try {
|
||||||
|
//init
|
||||||
|
addsInput.open();
|
||||||
|
oldInput.open();
|
||||||
|
mergeOutput.open();
|
||||||
|
init();
|
||||||
|
//merge
|
||||||
|
//findChanges();
|
||||||
|
mergeFiles();
|
||||||
|
mergeReferences();
|
||||||
|
mergeOutput.flush();
|
||||||
|
} finally {
|
||||||
|
//closes everything
|
||||||
|
oldInput.close();
|
||||||
|
addsInput.close();
|
||||||
|
mergeOutput.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Merges the files of the 2 indexes in the new index, removes the files
|
||||||
|
* to be removed, and records the changes made to propagate them to the
|
||||||
|
* word references.
|
||||||
|
*/
|
||||||
|
|
||||||
|
protected void mergeFiles() throws IOException {
|
||||||
|
int positionInMerge= 1;
|
||||||
|
int compare;
|
||||||
|
while (oldInput.hasMoreFiles() || addsInput.hasMoreFiles()) {
|
||||||
|
IndexedFile file1= oldInput.getCurrentFile();
|
||||||
|
IndexedFile file2= addsInput.getCurrentFile();
|
||||||
|
|
||||||
|
//if the file has been removed we don't take it into account
|
||||||
|
while (file1 != null && wasRemoved(file1, OLD_INDEX)) {
|
||||||
|
oldInput.moveToNextFile();
|
||||||
|
file1= oldInput.getCurrentFile();
|
||||||
|
}
|
||||||
|
while (file2 != null && wasRemoved(file2, ADDS_INDEX)) {
|
||||||
|
addsInput.moveToNextFile();
|
||||||
|
file2= addsInput.getCurrentFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
//the addsIndex was empty, we just removed files from the oldIndex
|
||||||
|
if (file1 == null && file2 == null)
|
||||||
|
break;
|
||||||
|
|
||||||
|
//test if we reached the end of one the 2 index
|
||||||
|
if (file1 == null)
|
||||||
|
compare= 1;
|
||||||
|
else if (file2 == null)
|
||||||
|
compare= -1;
|
||||||
|
else
|
||||||
|
compare= file1.getPath().compareTo(file2.getPath());
|
||||||
|
|
||||||
|
//records the changes to Make
|
||||||
|
if (compare == 0) {
|
||||||
|
//the file has been modified:
|
||||||
|
//we remove it from the oldIndex and add it to the addsIndex
|
||||||
|
removeFile(file1, OLD_INDEX);
|
||||||
|
mappingAdds[file2.getFileNumber()]= positionInMerge;
|
||||||
|
file1.setFileNumber(positionInMerge);
|
||||||
|
mergeOutput.addFile(file1);
|
||||||
|
oldInput.moveToNextFile();
|
||||||
|
addsInput.moveToNextFile();
|
||||||
|
} else if (compare < 0) {
|
||||||
|
mappingOld[file1.getFileNumber()]= positionInMerge;
|
||||||
|
file1.setFileNumber(positionInMerge);
|
||||||
|
mergeOutput.addFile(file1);
|
||||||
|
oldInput.moveToNextFile();
|
||||||
|
} else {
|
||||||
|
mappingAdds[file2.getFileNumber()]= positionInMerge;
|
||||||
|
file2.setFileNumber(positionInMerge);
|
||||||
|
mergeOutput.addFile(file2);
|
||||||
|
addsInput.moveToNextFile();
|
||||||
|
}
|
||||||
|
positionInMerge++;
|
||||||
|
}
|
||||||
|
mergeOutput.flushFiles();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Merges the files of the 2 indexes in the new index, according to the changes
|
||||||
|
* recorded during mergeFiles().
|
||||||
|
*/
|
||||||
|
protected void mergeReferences() throws IOException {
|
||||||
|
int compare;
|
||||||
|
while (oldInput.hasMoreWords() || addsInput.hasMoreWords()) {
|
||||||
|
WordEntry word1= oldInput.getCurrentWordEntry();
|
||||||
|
WordEntry word2= addsInput.getCurrentWordEntry();
|
||||||
|
|
||||||
|
if (word1 == null && word2 == null)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (word1 == null)
|
||||||
|
compare= 1;
|
||||||
|
else if (word2 == null)
|
||||||
|
compare= -1;
|
||||||
|
else
|
||||||
|
compare= Util.compare(word1.getWord(), word2.getWord());
|
||||||
|
if (compare < 0) {
|
||||||
|
word1.mapRefs(mappingOld);
|
||||||
|
mergeOutput.addWord(word1);
|
||||||
|
oldInput.moveToNextWordEntry();
|
||||||
|
} else if (compare > 0) {
|
||||||
|
word2.mapRefs(mappingAdds);
|
||||||
|
mergeOutput.addWord(word2);
|
||||||
|
addsInput.moveToNextWordEntry();
|
||||||
|
} else {
|
||||||
|
word1.mapRefs(mappingOld);
|
||||||
|
word2.mapRefs(mappingAdds);
|
||||||
|
word1.addRefs(word2.getRefs());
|
||||||
|
mergeOutput.addWord(word1);
|
||||||
|
addsInput.moveToNextWordEntry();
|
||||||
|
oldInput.moveToNextWordEntry();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mergeOutput.flushWords();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Records the deletion of one file.
|
||||||
|
*/
|
||||||
|
protected void removeFile(IndexedFile file, int index) {
|
||||||
|
if (index == OLD_INDEX)
|
||||||
|
mappingOld[file.getFileNumber()]= -1;
|
||||||
|
else
|
||||||
|
mappingAdds[file.getFileNumber()]= -1;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Returns whether the given file has to be removed from the given index
|
||||||
|
* (ADDS_INDEX or OLD_INDEX). If it has to be removed, the mergeFactory
|
||||||
|
* deletes it and records the changes.
|
||||||
|
*/
|
||||||
|
|
||||||
|
protected boolean wasRemoved(IndexedFile indexedFile, int index) {
|
||||||
|
String path= indexedFile.getPath();
|
||||||
|
if (index == OLD_INDEX) {
|
||||||
|
if (removedInOld.remove(path) != null) {
|
||||||
|
mappingOld[indexedFile.getFileNumber()]= -1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else if (index == ADDS_INDEX) {
|
||||||
|
Int lastRemoved= (Int) removedInAdds.get(path);
|
||||||
|
if (lastRemoved != null) {
|
||||||
|
int fileNum= indexedFile.getFileNumber();
|
||||||
|
if (lastRemoved.value >= fileNum) {
|
||||||
|
mappingAdds[fileNum]= -1;
|
||||||
|
//if (lastRemoved.value == fileNum) // ONLY if files in sorted order for names AND fileNums
|
||||||
|
//removedInAdds.remove(path);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2003 IBM Corporation and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Common Public License v0.5
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/cpl-v05.html
|
||||||
|
******************************************************************************/
|
||||||
|
/*
|
||||||
|
* Created on May 30, 2003
|
||||||
|
*/
|
||||||
|
package org.eclipse.cdt.internal.core.index.impl;
|
||||||
|
|
||||||
|
import java.util.Enumeration;
|
||||||
|
import java.util.Hashtable;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.internal.core.index.IDocument;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The properties of a document are stored into a hashtable.
|
||||||
|
* @see IDocument
|
||||||
|
*/
|
||||||
|
|
||||||
|
public abstract class PropertyDocument implements IDocument {
|
||||||
|
protected Hashtable properties;
|
||||||
|
public PropertyDocument() {
|
||||||
|
properties= new Hashtable(5);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @see IDocument#getProperty
|
||||||
|
*/
|
||||||
|
public String getProperty(String property) {
|
||||||
|
return (String) properties.get(property);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @see IDocument#getPropertyNames
|
||||||
|
*/
|
||||||
|
|
||||||
|
public Enumeration getPropertyNames() {
|
||||||
|
return properties.keys();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @see IDocument#setProperty
|
||||||
|
*/
|
||||||
|
|
||||||
|
public void setProperty(String property, String value) {
|
||||||
|
properties.put(property, value);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2003 IBM Corporation and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Common Public License v0.5
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/cpl-v05.html
|
||||||
|
******************************************************************************/
|
||||||
|
/*
|
||||||
|
* Created on Jun 1, 2003
|
||||||
|
*/
|
||||||
|
package org.eclipse.cdt.internal.core.index.impl;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.RandomAccessFile;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A safe subclass of RandomAccessFile, which ensure that it's closed
|
||||||
|
* on finalize.
|
||||||
|
*/
|
||||||
|
public class SafeRandomAccessFile extends RandomAccessFile {
|
||||||
|
public SafeRandomAccessFile(java.io.File file, String mode) throws java.io.IOException {
|
||||||
|
super(file, mode);
|
||||||
|
}
|
||||||
|
public SafeRandomAccessFile(String name, String mode) throws java.io.IOException {
|
||||||
|
super(name, mode);
|
||||||
|
}
|
||||||
|
protected void finalize() throws IOException {
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,177 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2003 IBM Corporation and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Common Public License v0.5
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/cpl-v05.html
|
||||||
|
******************************************************************************/
|
||||||
|
/*
|
||||||
|
* Created on Jun 1, 2003
|
||||||
|
*/
|
||||||
|
package org.eclipse.cdt.internal.core.index.impl;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.internal.core.index.IDocument;
|
||||||
|
import org.eclipse.cdt.internal.core.index.IEntryResult;
|
||||||
|
import org.eclipse.cdt.internal.core.index.IQueryResult;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A simpleIndexInput is an input on an in memory Index.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class SimpleIndexInput extends IndexInput {
|
||||||
|
protected WordEntry[] sortedWordEntries;
|
||||||
|
protected IndexedFile currentFile;
|
||||||
|
protected IndexedFile[] sortedFiles;
|
||||||
|
protected InMemoryIndex index;
|
||||||
|
|
||||||
|
public SimpleIndexInput(InMemoryIndex index) {
|
||||||
|
super();
|
||||||
|
this.index= index;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @see IndexInput#clearCache()
|
||||||
|
*/
|
||||||
|
public void clearCache() {
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @see IndexInput#close()
|
||||||
|
*/
|
||||||
|
public void close() throws IOException {
|
||||||
|
sortedFiles= null;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @see IndexInput#getCurrentFile()
|
||||||
|
*/
|
||||||
|
public IndexedFile getCurrentFile() throws IOException {
|
||||||
|
if (!hasMoreFiles())
|
||||||
|
return null;
|
||||||
|
return currentFile;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @see IndexInput#getIndexedFile(int)
|
||||||
|
*/
|
||||||
|
public IndexedFile getIndexedFile(int fileNum) throws IOException {
|
||||||
|
for (int i= 0; i < sortedFiles.length; i++)
|
||||||
|
if (sortedFiles[i].getFileNumber() == fileNum)
|
||||||
|
return sortedFiles[i];
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @see IndexInput#getIndexedFile(IDocument)
|
||||||
|
*/
|
||||||
|
public IndexedFile getIndexedFile(IDocument document) throws IOException {
|
||||||
|
String name= document.getName();
|
||||||
|
for (int i= index.getNumFiles(); i >= 1; i--) {
|
||||||
|
IndexedFile file= getIndexedFile(i);
|
||||||
|
if (name.equals(file.getPath()))
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @see IndexInput#getNumFiles()
|
||||||
|
*/
|
||||||
|
public int getNumFiles() {
|
||||||
|
return index.getNumFiles();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @see IndexInput#getNumWords()
|
||||||
|
*/
|
||||||
|
public int getNumWords() {
|
||||||
|
return sortedWordEntries.length;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @see IndexInput#getSource()
|
||||||
|
*/
|
||||||
|
public Object getSource() {
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
public void init() {
|
||||||
|
index.init();
|
||||||
|
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @see IndexInput#moveToNextFile()
|
||||||
|
*/
|
||||||
|
public void moveToNextFile() throws IOException {
|
||||||
|
filePosition++;
|
||||||
|
if (!hasMoreFiles()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
currentFile= sortedFiles[filePosition - 1];
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @see IndexInput#moveToNextWordEntry()
|
||||||
|
*/
|
||||||
|
public void moveToNextWordEntry() throws IOException {
|
||||||
|
wordPosition++;
|
||||||
|
if (hasMoreWords())
|
||||||
|
currentWordEntry= sortedWordEntries[wordPosition - 1];
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @see IndexInput#open()
|
||||||
|
*/
|
||||||
|
public void open() throws IOException {
|
||||||
|
sortedWordEntries= index.getSortedWordEntries();
|
||||||
|
sortedFiles= index.getSortedFiles();
|
||||||
|
filePosition= 1;
|
||||||
|
wordPosition= 1;
|
||||||
|
setFirstFile();
|
||||||
|
setFirstWord();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @see IndexInput#query(String)
|
||||||
|
*/
|
||||||
|
public IQueryResult[] query(String word) throws IOException {
|
||||||
|
char[] wordChar= word.toCharArray();
|
||||||
|
WordEntry wordEntry= index.getWordEntry(wordChar);
|
||||||
|
int[] fileNums= wordEntry.getRefs();
|
||||||
|
IQueryResult[] files= new IQueryResult[fileNums.length];
|
||||||
|
for (int i= 0; i < files.length; i++)
|
||||||
|
files[i]= getIndexedFile(fileNums[i]);
|
||||||
|
return files;
|
||||||
|
}
|
||||||
|
public IEntryResult[] queryEntriesPrefixedBy(char[] prefix) throws IOException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
public IQueryResult[] queryFilesReferringToPrefix(char[] prefix) throws IOException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @see IndexInput#queryInDocumentNames(String)
|
||||||
|
*/
|
||||||
|
public IQueryResult[] queryInDocumentNames(String word) throws IOException {
|
||||||
|
setFirstFile();
|
||||||
|
ArrayList matches= new ArrayList();
|
||||||
|
while (hasMoreFiles()) {
|
||||||
|
IndexedFile file= getCurrentFile();
|
||||||
|
if (file.getPath().indexOf(word) != -1)
|
||||||
|
matches.add(file.getPath());
|
||||||
|
moveToNextFile();
|
||||||
|
}
|
||||||
|
IQueryResult[] match= new IQueryResult[matches.size()];
|
||||||
|
matches.toArray(match);
|
||||||
|
return match;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @see IndexInput#setFirstFile()
|
||||||
|
*/
|
||||||
|
protected void setFirstFile() throws IOException {
|
||||||
|
filePosition= 1;
|
||||||
|
if (sortedFiles.length > 0) {
|
||||||
|
currentFile= sortedFiles[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @see IndexInput#setFirstWord()
|
||||||
|
*/
|
||||||
|
protected void setFirstWord() throws IOException {
|
||||||
|
wordPosition= 1;
|
||||||
|
if (sortedWordEntries.length > 0)
|
||||||
|
currentWordEntry= sortedWordEntries[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,341 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2003 IBM Corporation and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Common Public License v0.5
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/cpl-v05.html
|
||||||
|
******************************************************************************/
|
||||||
|
/*
|
||||||
|
* Created on Jun 1, 2003
|
||||||
|
*/
|
||||||
|
package org.eclipse.cdt.internal.core.index.impl;
|
||||||
|
|
||||||
|
import java.io.DataInput;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.io.UTFDataFormatException;
|
||||||
|
|
||||||
|
public class Util {
|
||||||
|
|
||||||
|
private Util() {
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Compares two strings lexicographically.
|
||||||
|
* The comparison is based on the Unicode value of each character in
|
||||||
|
* the strings.
|
||||||
|
*
|
||||||
|
* @return the value <code>0</code> if the str1 is equal to str2;
|
||||||
|
* a value less than <code>0</code> if str1
|
||||||
|
* is lexicographically less than str2;
|
||||||
|
* and a value greater than <code>0</code> if str1 is
|
||||||
|
* lexicographically greater than str2.
|
||||||
|
*/
|
||||||
|
public static int compare(char[] str1, char[] str2) {
|
||||||
|
int len1= str1.length;
|
||||||
|
int len2= str2.length;
|
||||||
|
int n= Math.min(len1, len2);
|
||||||
|
int i= 0;
|
||||||
|
while (n-- != 0) {
|
||||||
|
char c1= str1[i];
|
||||||
|
char c2= str2[i++];
|
||||||
|
if (c1 != c2) {
|
||||||
|
return c1 - c2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return len1 - len2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the length of the common prefix between s1 and s2.
|
||||||
|
*/
|
||||||
|
public static int prefixLength(char[] s1, char[] s2) {
|
||||||
|
int len= 0;
|
||||||
|
int max= Math.min(s1.length, s2.length);
|
||||||
|
for (int i= 0; i < max && s1[i] == s2[i]; ++i)
|
||||||
|
++len;
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Returns the length of the common prefix between s1 and s2.
|
||||||
|
*/
|
||||||
|
public static int prefixLength(String s1, String s2) {
|
||||||
|
int len= 0;
|
||||||
|
int max= Math.min(s1.length(), s2.length());
|
||||||
|
for (int i= 0; i < max && s1.charAt(i) == s2.charAt(i); ++i)
|
||||||
|
++len;
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
private static void quickSort(char[][] list, int left, int right) {
|
||||||
|
int original_left= left;
|
||||||
|
int original_right= right;
|
||||||
|
char[] mid= list[(left + right) / 2];
|
||||||
|
do {
|
||||||
|
while (compare(list[left], mid) < 0) {
|
||||||
|
left++;
|
||||||
|
}
|
||||||
|
while (compare(mid, list[right]) < 0) {
|
||||||
|
right--;
|
||||||
|
}
|
||||||
|
if (left <= right) {
|
||||||
|
char[] tmp= list[left];
|
||||||
|
list[left]= list[right];
|
||||||
|
list[right]= tmp;
|
||||||
|
left++;
|
||||||
|
right--;
|
||||||
|
}
|
||||||
|
} while (left <= right);
|
||||||
|
if (original_left < right) {
|
||||||
|
quickSort(list, original_left, right);
|
||||||
|
}
|
||||||
|
if (left < original_right) {
|
||||||
|
quickSort(list, left, original_right);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private static void quickSort(int[] list, int left, int right) {
|
||||||
|
int original_left= left;
|
||||||
|
int original_right= right;
|
||||||
|
int mid= list[(left + right) / 2];
|
||||||
|
do {
|
||||||
|
while (list[left] < mid) {
|
||||||
|
left++;
|
||||||
|
}
|
||||||
|
while (mid < list[right]) {
|
||||||
|
right--;
|
||||||
|
}
|
||||||
|
if (left <= right) {
|
||||||
|
int tmp= list[left];
|
||||||
|
list[left]= list[right];
|
||||||
|
list[right]= tmp;
|
||||||
|
left++;
|
||||||
|
right--;
|
||||||
|
}
|
||||||
|
} while (left <= right);
|
||||||
|
if (original_left < right) {
|
||||||
|
quickSort(list, original_left, right);
|
||||||
|
}
|
||||||
|
if (left < original_right) {
|
||||||
|
quickSort(list, left, original_right);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private static void quickSort(String[] list, int left, int right) {
|
||||||
|
int original_left= left;
|
||||||
|
int original_right= right;
|
||||||
|
String mid= list[(left + right) / 2];
|
||||||
|
do {
|
||||||
|
while (list[left].compareTo(mid) < 0) {
|
||||||
|
left++;
|
||||||
|
}
|
||||||
|
while (mid.compareTo(list[right]) < 0) {
|
||||||
|
right--;
|
||||||
|
}
|
||||||
|
if (left <= right) {
|
||||||
|
String tmp= list[left];
|
||||||
|
list[left]= list[right];
|
||||||
|
list[right]= tmp;
|
||||||
|
left++;
|
||||||
|
right--;
|
||||||
|
}
|
||||||
|
} while (left <= right);
|
||||||
|
if (original_left < right) {
|
||||||
|
quickSort(list, original_left, right);
|
||||||
|
}
|
||||||
|
if (left < original_right) {
|
||||||
|
quickSort(list, left, original_right);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private static void quickSort(IndexedFile[] list, int left, int right) {
|
||||||
|
int original_left= left;
|
||||||
|
int original_right= right;
|
||||||
|
String mid= list[(left + right) / 2].path;
|
||||||
|
do {
|
||||||
|
while (list[left].path.compareTo(mid) < 0) {
|
||||||
|
left++;
|
||||||
|
}
|
||||||
|
while (mid.compareTo(list[right].path) < 0) {
|
||||||
|
right--;
|
||||||
|
}
|
||||||
|
if (left <= right) {
|
||||||
|
IndexedFile tmp= list[left];
|
||||||
|
list[left]= list[right];
|
||||||
|
list[right]= tmp;
|
||||||
|
left++;
|
||||||
|
right--;
|
||||||
|
}
|
||||||
|
} while (left <= right);
|
||||||
|
if (original_left < right) {
|
||||||
|
quickSort(list, original_left, right);
|
||||||
|
}
|
||||||
|
if (left < original_right) {
|
||||||
|
quickSort(list, left, original_right);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private static void quickSort(WordEntry[] list, int left, int right) {
|
||||||
|
int original_left= left;
|
||||||
|
int original_right= right;
|
||||||
|
char[] mid= list[(left + right) / 2].fWord;
|
||||||
|
do {
|
||||||
|
while (compare(list[left].fWord, mid) < 0) {
|
||||||
|
left++;
|
||||||
|
}
|
||||||
|
while (compare(mid, list[right].fWord) < 0) {
|
||||||
|
right--;
|
||||||
|
}
|
||||||
|
if (left <= right) {
|
||||||
|
WordEntry tmp= list[left];
|
||||||
|
list[left]= list[right];
|
||||||
|
list[right]= tmp;
|
||||||
|
left++;
|
||||||
|
right--;
|
||||||
|
}
|
||||||
|
} while (left <= right);
|
||||||
|
if (original_left < right) {
|
||||||
|
quickSort(list, original_left, right);
|
||||||
|
}
|
||||||
|
if (left < original_right) {
|
||||||
|
quickSort(list, left, original_right);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Reads in a string from the specified data input stream. The
|
||||||
|
* string has been encoded using a modified UTF-8 format.
|
||||||
|
* <p>
|
||||||
|
* The first two bytes are read as if by
|
||||||
|
* <code>readUnsignedShort</code>. This value gives the number of
|
||||||
|
* following bytes that are in the encoded string, not
|
||||||
|
* the length of the resulting string. The following bytes are then
|
||||||
|
* interpreted as bytes encoding characters in the UTF-8 format
|
||||||
|
* and are converted into characters.
|
||||||
|
* <p>
|
||||||
|
* This method blocks until all the bytes are read, the end of the
|
||||||
|
* stream is detected, or an exception is thrown.
|
||||||
|
*
|
||||||
|
* @param in a data input stream.
|
||||||
|
* @return a Unicode string.
|
||||||
|
* @exception EOFException if the input stream reaches the end
|
||||||
|
* before all the bytes.
|
||||||
|
* @exception IOException if an I/O error occurs.
|
||||||
|
* @exception UTFDataFormatException if the bytes do not represent a
|
||||||
|
* valid UTF-8 encoding of a Unicode string.
|
||||||
|
* @see java.io.DataInputStream#readUnsignedShort()
|
||||||
|
*/
|
||||||
|
public final static char[] readUTF(DataInput in) throws IOException {
|
||||||
|
int utflen= in.readUnsignedShort();
|
||||||
|
char str[]= new char[utflen];
|
||||||
|
int count= 0;
|
||||||
|
int strlen= 0;
|
||||||
|
while (count < utflen) {
|
||||||
|
int c= in.readUnsignedByte();
|
||||||
|
int char2, char3;
|
||||||
|
switch (c >> 4) {
|
||||||
|
case 0 :
|
||||||
|
case 1 :
|
||||||
|
case 2 :
|
||||||
|
case 3 :
|
||||||
|
case 4 :
|
||||||
|
case 5 :
|
||||||
|
case 6 :
|
||||||
|
case 7 :
|
||||||
|
// 0xxxxxxx
|
||||||
|
count++;
|
||||||
|
str[strlen++]= (char) c;
|
||||||
|
break;
|
||||||
|
case 12 :
|
||||||
|
case 13 :
|
||||||
|
// 110x xxxx 10xx xxxx
|
||||||
|
count += 2;
|
||||||
|
if (count > utflen)
|
||||||
|
throw new UTFDataFormatException();
|
||||||
|
char2= in.readUnsignedByte();
|
||||||
|
if ((char2 & 0xC0) != 0x80)
|
||||||
|
throw new UTFDataFormatException();
|
||||||
|
str[strlen++]= (char) (((c & 0x1F) << 6) | (char2 & 0x3F));
|
||||||
|
break;
|
||||||
|
case 14 :
|
||||||
|
// 1110 xxxx 10xx xxxx 10xx xxxx
|
||||||
|
count += 3;
|
||||||
|
if (count > utflen)
|
||||||
|
throw new UTFDataFormatException();
|
||||||
|
char2= in.readUnsignedByte();
|
||||||
|
char3= in.readUnsignedByte();
|
||||||
|
if (((char2 & 0xC0) != 0x80) || ((char3 & 0xC0) != 0x80))
|
||||||
|
throw new UTFDataFormatException();
|
||||||
|
str[strlen++]= (char) (((c & 0x0F) << 12) | ((char2 & 0x3F) << 6) | ((char3 & 0x3F) << 0));
|
||||||
|
break;
|
||||||
|
default :
|
||||||
|
// 10xx xxxx, 1111 xxxx
|
||||||
|
throw new UTFDataFormatException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (strlen < utflen) {
|
||||||
|
System.arraycopy(str, 0, str= new char[strlen], 0, strlen);
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
public static void sort(char[][] list) {
|
||||||
|
if (list.length > 1)
|
||||||
|
quickSort(list, 0, list.length - 1);
|
||||||
|
}
|
||||||
|
public static void sort(int[] list) {
|
||||||
|
if (list.length > 1)
|
||||||
|
quickSort(list, 0, list.length - 1);
|
||||||
|
}
|
||||||
|
public static void sort(String[] list) {
|
||||||
|
if (list.length > 1)
|
||||||
|
quickSort(list, 0, list.length - 1);
|
||||||
|
}
|
||||||
|
public static void sort(IndexedFile[] list) {
|
||||||
|
if (list.length > 1)
|
||||||
|
quickSort(list, 0, list.length - 1);
|
||||||
|
}
|
||||||
|
public static void sort(WordEntry[] list) {
|
||||||
|
if (list.length > 1)
|
||||||
|
quickSort(list, 0, list.length - 1);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Writes a string to the given output stream using UTF-8
|
||||||
|
* encoding in a machine-independent manner.
|
||||||
|
* <p>
|
||||||
|
* First, two bytes are written to the output stream as if by the
|
||||||
|
* <code>writeShort</code> method giving the number of bytes to
|
||||||
|
* follow. This value is the number of bytes actually written out,
|
||||||
|
* not the length of the string. Following the length, each character
|
||||||
|
* of the string is output, in sequence, using the UTF-8 encoding
|
||||||
|
* for the character.
|
||||||
|
*
|
||||||
|
* @param str a string to be written.
|
||||||
|
* @exception IOException if an I/O error occurs.
|
||||||
|
* @since JDK1.0
|
||||||
|
*/
|
||||||
|
public static void writeUTF(OutputStream out, char[] str) throws IOException {
|
||||||
|
int strlen= str.length;
|
||||||
|
int utflen= 0;
|
||||||
|
for (int i= 0; i < strlen; i++) {
|
||||||
|
int c= str[i];
|
||||||
|
if ((c >= 0x0001) && (c <= 0x007F)) {
|
||||||
|
utflen++;
|
||||||
|
} else if (c > 0x07FF) {
|
||||||
|
utflen += 3;
|
||||||
|
} else {
|
||||||
|
utflen += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (utflen > 65535)
|
||||||
|
throw new UTFDataFormatException();
|
||||||
|
out.write((utflen >>> 8) & 0xFF);
|
||||||
|
out.write((utflen >>> 0) & 0xFF);
|
||||||
|
for (int i= 0; i < strlen; i++) {
|
||||||
|
int c= str[i];
|
||||||
|
if ((c >= 0x0001) && (c <= 0x007F)) {
|
||||||
|
out.write(c);
|
||||||
|
} else if (c > 0x07FF) {
|
||||||
|
out.write(0xE0 | ((c >> 12) & 0x0F));
|
||||||
|
out.write(0x80 | ((c >> 6) & 0x3F));
|
||||||
|
out.write(0x80 | ((c >> 0) & 0x3F));
|
||||||
|
} else {
|
||||||
|
out.write(0xC0 | ((c >> 6) & 0x1F));
|
||||||
|
out.write(0x80 | ((c >> 0) & 0x3F));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,156 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2003 IBM Corporation and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Common Public License v0.5
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/cpl-v05.html
|
||||||
|
******************************************************************************/
|
||||||
|
/*
|
||||||
|
* Created on Jun 1, 2003
|
||||||
|
*/
|
||||||
|
package org.eclipse.cdt.internal.core.index.impl;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.internal.core.search.CharOperation;
|
||||||
|
|
||||||
|
public class WordEntry {
|
||||||
|
protected char[] fWord;
|
||||||
|
protected int fNumRefs;
|
||||||
|
protected int[] fRefs;
|
||||||
|
public WordEntry() {
|
||||||
|
this(CharOperation.NO_CHAR);
|
||||||
|
}
|
||||||
|
public WordEntry(char[] word) {
|
||||||
|
fWord= word;
|
||||||
|
fNumRefs= 0;
|
||||||
|
fRefs= new int[1];
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Adds a reference and records the change in footprint.
|
||||||
|
*/
|
||||||
|
public int addRef(int fileNum) {
|
||||||
|
if (fNumRefs > 0 && fRefs[fNumRefs - 1] == fileNum) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (fNumRefs < fRefs.length) {
|
||||||
|
fRefs[fNumRefs++]= fileNum;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// For rt.jar, 73265 word entries are created. 51997 have 1 ref, then 9438, 3738, 1980, 1214, 779, 547, 429, 371 etc.
|
||||||
|
int newSize= fNumRefs < 4 ? 4 : fNumRefs * 2; // so will start @ 1, grow to 4, 8, 16, 32, 64 etc.
|
||||||
|
System.arraycopy(fRefs, 0, fRefs= new int[newSize], 0, fNumRefs);
|
||||||
|
fRefs[fNumRefs++]= fileNum;
|
||||||
|
return (newSize - fNumRefs + 1) * 4;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Adds a set of references and records the change in footprint.
|
||||||
|
*/
|
||||||
|
public void addRefs(int[] refs) {
|
||||||
|
int[] newRefs= new int[fNumRefs + refs.length];
|
||||||
|
int pos1= 0;
|
||||||
|
int pos2= 0;
|
||||||
|
int posNew= 0;
|
||||||
|
int compare;
|
||||||
|
int r1= 0;
|
||||||
|
int r2= 0;
|
||||||
|
while (pos1 < fNumRefs || pos2 < refs.length) {
|
||||||
|
if (pos1 >= fNumRefs) {
|
||||||
|
r2= refs[pos2];
|
||||||
|
compare= -1;
|
||||||
|
} else if (pos2 >= refs.length) {
|
||||||
|
compare= 1;
|
||||||
|
r1= fRefs[pos1];
|
||||||
|
} else {
|
||||||
|
r1= fRefs[pos1];
|
||||||
|
r2= refs[pos2];
|
||||||
|
compare= r2 - r1;
|
||||||
|
}
|
||||||
|
if (compare > 0) {
|
||||||
|
newRefs[posNew]= r1;
|
||||||
|
posNew++;
|
||||||
|
pos1++;
|
||||||
|
} else {
|
||||||
|
if (r2 != 0) {
|
||||||
|
newRefs[posNew]= r2;
|
||||||
|
posNew++;
|
||||||
|
}
|
||||||
|
pos2++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fRefs= newRefs;
|
||||||
|
fNumRefs= posNew;
|
||||||
|
/*for (int i = 0; i < refs.length; i++)
|
||||||
|
addRef(refs[i]);
|
||||||
|
int[] newRefs = new int[fNumRefs];
|
||||||
|
System.arraycopy(fRefs, 0, newRefs, 0, fNumRefs);
|
||||||
|
fRefs = newRefs;
|
||||||
|
Util.sort(fRefs);*/
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Returns the size of the wordEntry
|
||||||
|
*/
|
||||||
|
public int footprint() {
|
||||||
|
return 8 + (3 * 4) + (8 + fWord.length * 2) + (8 + fRefs.length * 4);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Returns the number of references, e.g. the number of files this word appears in.
|
||||||
|
*/
|
||||||
|
public int getNumRefs() {
|
||||||
|
return fNumRefs;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* returns the file number in the i position in the list of references.
|
||||||
|
*/
|
||||||
|
public int getRef(int i) {
|
||||||
|
if (i < fNumRefs) return fRefs[i];
|
||||||
|
throw new IndexOutOfBoundsException();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Returns the references of the wordEntry (the number of the files it appears in).
|
||||||
|
*/
|
||||||
|
public int[] getRefs() {
|
||||||
|
int[] result= new int[fNumRefs];
|
||||||
|
System.arraycopy(fRefs, 0, result, 0, fNumRefs);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* returns the word of the wordEntry.
|
||||||
|
*/
|
||||||
|
public char[] getWord() {
|
||||||
|
return fWord;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Changes the references of the wordEntry to match the mapping. For example,<br>
|
||||||
|
* if the current references are [1 3 4]<br>
|
||||||
|
* and mapping is [1 2 3 4 5]<br>
|
||||||
|
* in references 1 becomes mapping[1] = 2, 3->4, and 4->5<br>
|
||||||
|
* => references = [2 4 5].<br>
|
||||||
|
*/
|
||||||
|
public void mapRefs(int[] mappings) {
|
||||||
|
int position= 0;
|
||||||
|
for (int i= 0; i < fNumRefs; i++) {
|
||||||
|
int map= mappings[fRefs[i]];
|
||||||
|
if (map != -1 && map != 0)
|
||||||
|
fRefs[position++]= map;
|
||||||
|
}
|
||||||
|
fNumRefs= position;
|
||||||
|
|
||||||
|
//to be changed!
|
||||||
|
System.arraycopy(fRefs, 0, (fRefs= new int[fNumRefs]), 0, fNumRefs);
|
||||||
|
Util.sort(fRefs);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Clears the wordEntry.
|
||||||
|
*/
|
||||||
|
public void reset(char[] word) {
|
||||||
|
for (int i= fNumRefs; i-- > 0;) {
|
||||||
|
fRefs[i]= 0;
|
||||||
|
}
|
||||||
|
fNumRefs= 0;
|
||||||
|
fWord= word;
|
||||||
|
}
|
||||||
|
public String toString() {
|
||||||
|
return new String(fWord);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,83 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2003 IBM Corporation and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Common Public License v0.5
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/cpl-v05.html
|
||||||
|
******************************************************************************/
|
||||||
|
/*
|
||||||
|
* Created on Jun 1, 2003
|
||||||
|
*/
|
||||||
|
package org.eclipse.cdt.internal.core.index.impl;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.internal.core.search.CharOperation;
|
||||||
|
|
||||||
|
public final class WordEntryHashedArray {
|
||||||
|
|
||||||
|
// to avoid using Enumerations, walk the objects skipping nulls
|
||||||
|
public WordEntry elements[];
|
||||||
|
public int elementSize; // number of elements in the table
|
||||||
|
public int threshold;
|
||||||
|
|
||||||
|
public WordEntryHashedArray(int size) {
|
||||||
|
if (size < 7) size = 7;
|
||||||
|
this.elements = new WordEntry[2 * size + 1];
|
||||||
|
this.elementSize = 0;
|
||||||
|
this.threshold = size + 1; // size is the expected number of elements
|
||||||
|
}
|
||||||
|
|
||||||
|
public WordEntry add(WordEntry entry) {
|
||||||
|
int length = elements.length;
|
||||||
|
char[] word = entry.getWord();
|
||||||
|
int index = CharOperation.hashCode(word) % length;
|
||||||
|
WordEntry current;
|
||||||
|
while ((current = elements[index]) != null) {
|
||||||
|
if (CharOperation.equals(current.getWord(), word)) return elements[index] = entry;
|
||||||
|
if (++index == length) index = 0;
|
||||||
|
}
|
||||||
|
elements[index] = entry;
|
||||||
|
|
||||||
|
// assumes the threshold is never equal to the size of the table
|
||||||
|
if (++elementSize > threshold) grow();
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
public WordEntry[] asArray() {
|
||||||
|
WordEntry[] array = new WordEntry[elementSize];
|
||||||
|
for (int i = 0, j = 0, length = elements.length; i < length; i++) {
|
||||||
|
WordEntry current = elements[i];
|
||||||
|
if (current != null) array[j++] = current;
|
||||||
|
}
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
public WordEntry get(char[] word) {
|
||||||
|
int length = elements.length;
|
||||||
|
int index = CharOperation.hashCode(word) % length;
|
||||||
|
WordEntry current;
|
||||||
|
while ((current = elements[index]) != null) {
|
||||||
|
if (CharOperation.equals(current.getWord(), word)) return current;
|
||||||
|
if (++index == length) index = 0;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void grow() {
|
||||||
|
WordEntryHashedArray newArray = new WordEntryHashedArray(elementSize * 2); // double the number of expected elements
|
||||||
|
for (int i = 0, length = elements.length; i < length; i++)
|
||||||
|
if (elements[i] != null)
|
||||||
|
newArray.add(elements[i]);
|
||||||
|
|
||||||
|
this.elements = newArray.elements;
|
||||||
|
this.elementSize = newArray.elementSize;
|
||||||
|
this.threshold = newArray.threshold;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
String s = ""; //$NON-NLS-1$
|
||||||
|
WordEntry[] entries = asArray();
|
||||||
|
for (int i = 0, length = entries.length; i < length; i++)
|
||||||
|
s += entries[i].toString() + "\n"; //$NON-NLS-1$
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,93 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2003 IBM Corporation and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Common Public License v0.5
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/cpl-v05.html
|
||||||
|
******************************************************************************/
|
||||||
|
/*
|
||||||
|
* Created on Jun 1, 2003
|
||||||
|
*/
|
||||||
|
package org.eclipse.cdt.internal.core.search;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hashtable for non-zero int keys.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public final class HashtableOfInt {
|
||||||
|
// to avoid using Enumerations, walk the individual tables skipping nulls
|
||||||
|
public int[] keyTable;
|
||||||
|
public Object[] valueTable;
|
||||||
|
|
||||||
|
int elementSize; // number of elements in the table
|
||||||
|
int threshold;
|
||||||
|
public HashtableOfInt() {
|
||||||
|
this(13);
|
||||||
|
}
|
||||||
|
public HashtableOfInt(int size) {
|
||||||
|
this.elementSize = 0;
|
||||||
|
this.threshold = size; // size represents the expected number of elements
|
||||||
|
int extraRoom = (int) (size * 1.75f);
|
||||||
|
if (this.threshold == extraRoom)
|
||||||
|
extraRoom++;
|
||||||
|
this.keyTable = new int[extraRoom];
|
||||||
|
this.valueTable = new Object[extraRoom];
|
||||||
|
}
|
||||||
|
public boolean containsKey(int key) {
|
||||||
|
int index = key % valueTable.length;
|
||||||
|
int currentKey;
|
||||||
|
while ((currentKey = keyTable[index]) != 0) {
|
||||||
|
if (currentKey == key)
|
||||||
|
return true;
|
||||||
|
index = (index + 1) % keyTable.length;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
public Object get(int key) {
|
||||||
|
int index = key % valueTable.length;
|
||||||
|
int currentKey;
|
||||||
|
while ((currentKey = keyTable[index]) != 0) {
|
||||||
|
if (currentKey == key) return valueTable[index];
|
||||||
|
index = (index + 1) % keyTable.length;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
public Object put(int key, Object value) {
|
||||||
|
int index = key % valueTable.length;
|
||||||
|
int currentKey;
|
||||||
|
while ((currentKey = keyTable[index]) != 0) {
|
||||||
|
if (currentKey == key) return valueTable[index] = value;
|
||||||
|
index = (index + 1) % keyTable.length;
|
||||||
|
}
|
||||||
|
keyTable[index] = key;
|
||||||
|
valueTable[index] = value;
|
||||||
|
|
||||||
|
// assumes the threshold is never equal to the size of the table
|
||||||
|
if (++elementSize > threshold)
|
||||||
|
rehash();
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
private void rehash() {
|
||||||
|
HashtableOfInt newHashtable = new HashtableOfInt(elementSize * 2); // double the number of expected elements
|
||||||
|
int currentKey;
|
||||||
|
for (int i = keyTable.length; --i >= 0;)
|
||||||
|
if ((currentKey = keyTable[i]) != 0)
|
||||||
|
newHashtable.put(currentKey, valueTable[i]);
|
||||||
|
|
||||||
|
this.keyTable = newHashtable.keyTable;
|
||||||
|
this.valueTable = newHashtable.valueTable;
|
||||||
|
this.threshold = newHashtable.threshold;
|
||||||
|
}
|
||||||
|
public int size() {
|
||||||
|
return elementSize;
|
||||||
|
}
|
||||||
|
public String toString() {
|
||||||
|
String s = ""; //$NON-NLS-1$
|
||||||
|
Object object;
|
||||||
|
for (int i = 0, length = valueTable.length; i < length; i++)
|
||||||
|
if ((object = valueTable[i]) != null)
|
||||||
|
s += keyTable[i] + " -> " + object.toString() + "\n"; //$NON-NLS-2$ //$NON-NLS-1$
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,153 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2003 IBM Corporation and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Common Public License v0.5
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/cpl-v05.html
|
||||||
|
******************************************************************************/
|
||||||
|
/*
|
||||||
|
* Created on May 30, 2003
|
||||||
|
*/
|
||||||
|
package org.eclipse.cdt.internal.core.search;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A simple lookup table is a non-synchronized Hashtable, whose keys
|
||||||
|
* and values are Objects. It also uses linear probing to resolve collisions
|
||||||
|
* rather than a linked list of hash table entries.
|
||||||
|
*/
|
||||||
|
public final class SimpleLookupTable implements Cloneable {
|
||||||
|
|
||||||
|
// to avoid using Enumerations, walk the individual tables skipping nulls
|
||||||
|
public Object[] keyTable;
|
||||||
|
public Object[] valueTable;
|
||||||
|
public int elementSize; // number of elements in the table
|
||||||
|
public int threshold;
|
||||||
|
|
||||||
|
public SimpleLookupTable() {
|
||||||
|
this(13);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SimpleLookupTable(int size) {
|
||||||
|
if (size < 3) size = 3;
|
||||||
|
this.elementSize = 0;
|
||||||
|
this.threshold = size + 1; // size is the expected number of elements
|
||||||
|
int tableLength = 2 * size + 1;
|
||||||
|
this.keyTable = new Object[tableLength];
|
||||||
|
this.valueTable = new Object[tableLength];
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object clone() throws CloneNotSupportedException {
|
||||||
|
SimpleLookupTable result = (SimpleLookupTable) super.clone();
|
||||||
|
result.elementSize = this.elementSize;
|
||||||
|
result.threshold = this.threshold;
|
||||||
|
|
||||||
|
int length = this.keyTable.length;
|
||||||
|
result.keyTable = new Object[length];
|
||||||
|
System.arraycopy(this.keyTable, 0, result.keyTable, 0, length);
|
||||||
|
|
||||||
|
length = this.valueTable.length;
|
||||||
|
result.valueTable = new Object[length];
|
||||||
|
System.arraycopy(this.valueTable, 0, result.valueTable, 0, length);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean containsKey(Object key) {
|
||||||
|
int length = keyTable.length;
|
||||||
|
int index = (key.hashCode() & 0x7FFFFFFF) % length;
|
||||||
|
Object currentKey;
|
||||||
|
while ((currentKey = keyTable[index]) != null) {
|
||||||
|
if (currentKey.equals(key)) return true;
|
||||||
|
if (++index == length) index = 0;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object get(Object key) {
|
||||||
|
int length = keyTable.length;
|
||||||
|
int index = (key.hashCode() & 0x7FFFFFFF) % length;
|
||||||
|
Object currentKey;
|
||||||
|
while ((currentKey = keyTable[index]) != null) {
|
||||||
|
if (currentKey.equals(key)) return valueTable[index];
|
||||||
|
if (++index == length) index = 0;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object keyForValue(Object valueToMatch) {
|
||||||
|
if (valueToMatch != null)
|
||||||
|
for (int i = 0, l = valueTable.length; i < l; i++)
|
||||||
|
if (valueToMatch.equals(valueTable[i]))
|
||||||
|
return keyTable[i];
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object put(Object key, Object value) {
|
||||||
|
int length = keyTable.length;
|
||||||
|
int index = (key.hashCode() & 0x7FFFFFFF) % length;
|
||||||
|
Object currentKey;
|
||||||
|
while ((currentKey = keyTable[index]) != null) {
|
||||||
|
if (currentKey.equals(key)) return valueTable[index] = value;
|
||||||
|
if (++index == length) index = 0;
|
||||||
|
}
|
||||||
|
keyTable[index] = key;
|
||||||
|
valueTable[index] = value;
|
||||||
|
|
||||||
|
// assumes the threshold is never equal to the size of the table
|
||||||
|
if (++elementSize > threshold) rehash();
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeKey(Object key) {
|
||||||
|
int length = keyTable.length;
|
||||||
|
int index = (key.hashCode() & 0x7FFFFFFF) % length;
|
||||||
|
Object currentKey;
|
||||||
|
while ((currentKey = keyTable[index]) != null) {
|
||||||
|
if (currentKey.equals(key)) {
|
||||||
|
elementSize--;
|
||||||
|
keyTable[index] = null;
|
||||||
|
valueTable[index] = null;
|
||||||
|
if (keyTable[index + 1 == length ? 0 : index + 1] != null)
|
||||||
|
rehash(); // only needed if a possible collision existed
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (++index == length) index = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeValue(Object valueToRemove) {
|
||||||
|
boolean rehash = false;
|
||||||
|
for (int i = 0, l = valueTable.length; i < l; i++) {
|
||||||
|
Object value = valueTable[i];
|
||||||
|
if (value != null && value.equals(valueToRemove)) {
|
||||||
|
elementSize--;
|
||||||
|
keyTable[i] = null;
|
||||||
|
valueTable[i] = null;
|
||||||
|
if (!rehash && keyTable[i + 1 == l ? 0 : i + 1] != null)
|
||||||
|
rehash = true; // only needed if a possible collision existed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (rehash) rehash();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void rehash() {
|
||||||
|
SimpleLookupTable newLookupTable = new SimpleLookupTable(elementSize * 2); // double the number of expected elements
|
||||||
|
Object currentKey;
|
||||||
|
for (int i = keyTable.length; --i >= 0;)
|
||||||
|
if ((currentKey = keyTable[i]) != null)
|
||||||
|
newLookupTable.put(currentKey, valueTable[i]);
|
||||||
|
|
||||||
|
this.keyTable = newLookupTable.keyTable;
|
||||||
|
this.valueTable = newLookupTable.valueTable;
|
||||||
|
this.elementSize = newLookupTable.elementSize;
|
||||||
|
this.threshold = newLookupTable.threshold;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
String s = ""; //$NON-NLS-1$
|
||||||
|
Object object;
|
||||||
|
for (int i = 0, l = valueTable.length; i < l; i++)
|
||||||
|
if ((object = valueTable[i]) != null)
|
||||||
|
s += keyTable[i].toString() + " -> " + object.toString() + "\n"; //$NON-NLS-2$ //$NON-NLS-1$
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,374 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2003 IBM Corporation and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Common Public License v0.5
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/cpl-v05.html
|
||||||
|
******************************************************************************/
|
||||||
|
/*
|
||||||
|
* Created on May 30, 2003
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.eclipse.cdt.internal.core.search;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.MissingResourceException;
|
||||||
|
import java.util.ResourceBundle;
|
||||||
|
import java.io.BufferedInputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.util.HashSet;
|
||||||
|
|
||||||
|
import org.eclipse.core.resources.IContainer;
|
||||||
|
import org.eclipse.core.resources.IResource;
|
||||||
|
import org.eclipse.core.runtime.IPath;
|
||||||
|
|
||||||
|
public class Util {
|
||||||
|
|
||||||
|
private final static char[] DOUBLE_QUOTES = "''".toCharArray(); //$NON-NLS-1$
|
||||||
|
private final static char[] SINGLE_QUOTE = "'".toCharArray(); //$NON-NLS-1$
|
||||||
|
private static final int DEFAULT_READING_SIZE = 8192;
|
||||||
|
|
||||||
|
/* Bundle containing messages */
|
||||||
|
protected static ResourceBundle bundle;
|
||||||
|
private final static String bundleName = "org.eclipse.cdt.internal.core.search.messages"; //$NON-NLS-1$
|
||||||
|
static {
|
||||||
|
relocalize();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Lookup the message with the given ID in this catalog and bind its
|
||||||
|
* substitution locations with the given strings.
|
||||||
|
*/
|
||||||
|
public static String bind(String id, String binding1, String binding2) {
|
||||||
|
return bind(id, new String[] {binding1, binding2});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Lookup the message with the given ID in this catalog and bind its
|
||||||
|
* substitution locations with the given string.
|
||||||
|
*/
|
||||||
|
public static String bind(String id, String binding) {
|
||||||
|
return bind(id, new String[] {binding});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Lookup the message with the given ID in this catalog and bind its
|
||||||
|
* substitution locations with the given string values.
|
||||||
|
*/
|
||||||
|
public static String bind(String id, String[] bindings) {
|
||||||
|
if (id == null)
|
||||||
|
return "No message available"; //$NON-NLS-1$
|
||||||
|
String message = null;
|
||||||
|
try {
|
||||||
|
message = bundle.getString(id);
|
||||||
|
} catch (MissingResourceException e) {
|
||||||
|
// If we got an exception looking for the message, fail gracefully by just returning
|
||||||
|
// the id we were looking for. In most cases this is semi-informative so is not too bad.
|
||||||
|
return "Missing message: " + id + " in: " + bundleName; //$NON-NLS-2$ //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
// for compatibility with MessageFormat which eliminates double quotes in original message
|
||||||
|
char[] messageWithNoDoubleQuotes =
|
||||||
|
CharOperation.replace(message.toCharArray(), DOUBLE_QUOTES, SINGLE_QUOTE);
|
||||||
|
message = new String(messageWithNoDoubleQuotes);
|
||||||
|
|
||||||
|
if (bindings == null)
|
||||||
|
return message;
|
||||||
|
int length = message.length();
|
||||||
|
int start = -1;
|
||||||
|
int end = length;
|
||||||
|
StringBuffer output = new StringBuffer(80);
|
||||||
|
while (true) {
|
||||||
|
if ((end = message.indexOf('{', start)) > -1) {
|
||||||
|
output.append(message.substring(start + 1, end));
|
||||||
|
if ((start = message.indexOf('}', end)) > -1) {
|
||||||
|
int index = -1;
|
||||||
|
try {
|
||||||
|
index = Integer.parseInt(message.substring(end + 1, start));
|
||||||
|
output.append(bindings[index]);
|
||||||
|
} catch (NumberFormatException nfe) {
|
||||||
|
output.append(message.substring(end + 1, start + 1));
|
||||||
|
} catch (ArrayIndexOutOfBoundsException e) {
|
||||||
|
output.append("{missing " + Integer.toString(index) + "}"); //$NON-NLS-2$ //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
output.append(message.substring(end, length));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
output.append(message.substring(start + 1, length));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return output.toString();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Lookup the message with the given ID in this catalog
|
||||||
|
*/
|
||||||
|
public static String bind(String id) {
|
||||||
|
return bind(id, (String[])null);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Creates a NLS catalog for the given locale.
|
||||||
|
*/
|
||||||
|
public static void relocalize() {
|
||||||
|
try {
|
||||||
|
bundle = ResourceBundle.getBundle(bundleName, Locale.getDefault());
|
||||||
|
} catch(MissingResourceException e) {
|
||||||
|
System.out.println("Missing resource : " + bundleName.replace('.', '/') + ".properties for locale " + Locale.getDefault()); //$NON-NLS-1$//$NON-NLS-2$
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the contents of the given file as a byte array.
|
||||||
|
* @throws IOException if a problem occured reading the file.
|
||||||
|
*/
|
||||||
|
public static byte[] getFileByteContent(File file) throws IOException {
|
||||||
|
InputStream stream = null;
|
||||||
|
try {
|
||||||
|
stream = new BufferedInputStream(new FileInputStream(file));
|
||||||
|
return getInputStreamAsByteArray(stream, (int) file.length());
|
||||||
|
} finally {
|
||||||
|
if (stream != null) {
|
||||||
|
try {
|
||||||
|
stream.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Returns the contents of the given file as a char array.
|
||||||
|
* When encoding is null, then the platform default one is used
|
||||||
|
* @throws IOException if a problem occured reading the file.
|
||||||
|
*/
|
||||||
|
public static char[] getFileCharContent(File file, String encoding) throws IOException {
|
||||||
|
InputStream stream = null;
|
||||||
|
try {
|
||||||
|
stream = new BufferedInputStream(new FileInputStream(file));
|
||||||
|
return Util.getInputStreamAsCharArray(stream, (int) file.length(), encoding);
|
||||||
|
} finally {
|
||||||
|
if (stream != null) {
|
||||||
|
try {
|
||||||
|
stream.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the given input stream's contents as a byte array.
|
||||||
|
* If a length is specified (ie. if length != -1), only length bytes
|
||||||
|
* are returned. Otherwise all bytes in the stream are returned.
|
||||||
|
* Note this doesn't close the stream.
|
||||||
|
* @throws IOException if a problem occured reading the stream.
|
||||||
|
*/
|
||||||
|
public static byte[] getInputStreamAsByteArray(InputStream stream, int length)
|
||||||
|
throws IOException {
|
||||||
|
byte[] contents;
|
||||||
|
if (length == -1) {
|
||||||
|
contents = new byte[0];
|
||||||
|
int contentsLength = 0;
|
||||||
|
int amountRead = -1;
|
||||||
|
do {
|
||||||
|
int amountRequested = Math.max(stream.available(), DEFAULT_READING_SIZE); // read at least 8K
|
||||||
|
|
||||||
|
// resize contents if needed
|
||||||
|
if (contentsLength + amountRequested > contents.length) {
|
||||||
|
System.arraycopy(
|
||||||
|
contents,
|
||||||
|
0,
|
||||||
|
contents = new byte[contentsLength + amountRequested],
|
||||||
|
0,
|
||||||
|
contentsLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
// read as many bytes as possible
|
||||||
|
amountRead = stream.read(contents, contentsLength, amountRequested);
|
||||||
|
|
||||||
|
if (amountRead > 0) {
|
||||||
|
// remember length of contents
|
||||||
|
contentsLength += amountRead;
|
||||||
|
}
|
||||||
|
} while (amountRead != -1);
|
||||||
|
|
||||||
|
// resize contents if necessary
|
||||||
|
if (contentsLength < contents.length) {
|
||||||
|
System.arraycopy(
|
||||||
|
contents,
|
||||||
|
0,
|
||||||
|
contents = new byte[contentsLength],
|
||||||
|
0,
|
||||||
|
contentsLength);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
contents = new byte[length];
|
||||||
|
int len = 0;
|
||||||
|
int readSize = 0;
|
||||||
|
while ((readSize != -1) && (len != length)) {
|
||||||
|
// See PR 1FMS89U
|
||||||
|
// We record first the read size. In this case len is the actual read size.
|
||||||
|
len += readSize;
|
||||||
|
readSize = stream.read(contents, len, length - len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return contents;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the given input stream's contents as a character array.
|
||||||
|
* If a length is specified (ie. if length != -1), only length chars
|
||||||
|
* are returned. Otherwise all chars in the stream are returned.
|
||||||
|
* Note this doesn't close the stream.
|
||||||
|
* @throws IOException if a problem occured reading the stream.
|
||||||
|
*/
|
||||||
|
public static char[] getInputStreamAsCharArray(InputStream stream, int length, String encoding)
|
||||||
|
throws IOException {
|
||||||
|
InputStreamReader reader = null;
|
||||||
|
reader = encoding == null
|
||||||
|
? new InputStreamReader(stream)
|
||||||
|
: new InputStreamReader(stream, encoding);
|
||||||
|
char[] contents;
|
||||||
|
if (length == -1) {
|
||||||
|
contents = CharOperation.NO_CHAR;
|
||||||
|
int contentsLength = 0;
|
||||||
|
int amountRead = -1;
|
||||||
|
do {
|
||||||
|
int amountRequested = Math.max(stream.available(), DEFAULT_READING_SIZE); // read at least 8K
|
||||||
|
|
||||||
|
// resize contents if needed
|
||||||
|
if (contentsLength + amountRequested > contents.length) {
|
||||||
|
System.arraycopy(
|
||||||
|
contents,
|
||||||
|
0,
|
||||||
|
contents = new char[contentsLength + amountRequested],
|
||||||
|
0,
|
||||||
|
contentsLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
// read as many chars as possible
|
||||||
|
amountRead = reader.read(contents, contentsLength, amountRequested);
|
||||||
|
|
||||||
|
if (amountRead > 0) {
|
||||||
|
// remember length of contents
|
||||||
|
contentsLength += amountRead;
|
||||||
|
}
|
||||||
|
} while (amountRead != -1);
|
||||||
|
|
||||||
|
// resize contents if necessary
|
||||||
|
if (contentsLength < contents.length) {
|
||||||
|
System.arraycopy(
|
||||||
|
contents,
|
||||||
|
0,
|
||||||
|
contents = new char[contentsLength],
|
||||||
|
0,
|
||||||
|
contentsLength);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
contents = new char[length];
|
||||||
|
int len = 0;
|
||||||
|
int readSize = 0;
|
||||||
|
while ((readSize != -1) && (len != length)) {
|
||||||
|
// See PR 1FMS89U
|
||||||
|
// We record first the read size. In this case len is the actual read size.
|
||||||
|
len += readSize;
|
||||||
|
readSize = reader.read(contents, len, length - len);
|
||||||
|
}
|
||||||
|
// See PR 1FMS89U
|
||||||
|
// Now we need to resize in case the default encoding used more than one byte for each
|
||||||
|
// character
|
||||||
|
if (len != length)
|
||||||
|
System.arraycopy(contents, 0, (contents = new char[len]), 0, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
return contents;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method - returns the targeted item (IResource if internal or java.io.File if external),
|
||||||
|
* or null if unbound
|
||||||
|
* Internal items must be referred to using container relative paths.
|
||||||
|
*/
|
||||||
|
public static Object getTarget(IContainer container, IPath path, boolean checkResourceExistence) {
|
||||||
|
|
||||||
|
if (path == null) return null;
|
||||||
|
|
||||||
|
// lookup - inside the container
|
||||||
|
if (path.getDevice() == null) { // container relative paths should not contain a device
|
||||||
|
// (see http://dev.eclipse.org/bugs/show_bug.cgi?id=18684)
|
||||||
|
// (case of a workspace rooted at d:\ )
|
||||||
|
IResource resource = container.findMember(path);
|
||||||
|
if (resource != null){
|
||||||
|
if (!checkResourceExistence ||resource.exists()) return resource;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if path is relative, it cannot be an external path
|
||||||
|
// (see http://dev.eclipse.org/bugs/show_bug.cgi?id=22517)
|
||||||
|
if (!path.isAbsolute()) return null;
|
||||||
|
|
||||||
|
// lookup - outside the container
|
||||||
|
File externalFile = new File(path.toOSString());
|
||||||
|
if (!checkResourceExistence) {
|
||||||
|
return externalFile;
|
||||||
|
} else if (existingExternalFiles.contains(externalFile)) {
|
||||||
|
return externalFile;
|
||||||
|
} else {
|
||||||
|
//TODO: BOG do we need to add something here?
|
||||||
|
/*
|
||||||
|
if (JavaModelManager.ZIP_ACCESS_VERBOSE) {
|
||||||
|
System.out.println("(" + Thread.currentThread() + ") [JavaModel.getTarget(...)] Checking existence of " + path.toString()); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
if (externalFile.exists()) {
|
||||||
|
// cache external file
|
||||||
|
existingExternalFiles.add(externalFile);
|
||||||
|
return externalFile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* A set of java.io.Files used as a cache of external jars that
|
||||||
|
* are known to be existing.
|
||||||
|
* Note this cache is kept for the whole session.
|
||||||
|
*/
|
||||||
|
public static HashSet existingExternalFiles = new HashSet();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns whether the given resource matches one of the exclusion patterns.
|
||||||
|
*
|
||||||
|
* @see IClasspathEntry#getExclusionPatterns
|
||||||
|
*/
|
||||||
|
public final static boolean isExcluded(IResource resource, char[][] exclusionPatterns) {
|
||||||
|
IPath path = resource.getFullPath();
|
||||||
|
// ensure that folders are only excluded if all of their children are excluded
|
||||||
|
if (resource.getType() == IResource.FOLDER)
|
||||||
|
path = path.append("*"); //$NON-NLS-1$
|
||||||
|
return isExcluded(path, exclusionPatterns);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns whether the given resource path matches one of the exclusion
|
||||||
|
* patterns.
|
||||||
|
*
|
||||||
|
* @see IClasspathEntry#getExclusionPatterns
|
||||||
|
*/
|
||||||
|
public final static boolean isExcluded(IPath resourcePath, char[][] exclusionPatterns) {
|
||||||
|
if (exclusionPatterns == null) return false;
|
||||||
|
char[] path = resourcePath.toString().toCharArray();
|
||||||
|
for (int i = 0, length = exclusionPatterns.length; i < length; i++)
|
||||||
|
if (CharOperation.pathMatch(exclusionPatterns[i], path, true, '/'))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,143 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2003 IBM Corporation and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Common Public License v0.5
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/cpl-v05.html
|
||||||
|
******************************************************************************/
|
||||||
|
/*
|
||||||
|
* Created on May 31, 2003
|
||||||
|
*/
|
||||||
|
package org.eclipse.cdt.internal.core.search.indexing;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.core.parser.ast.ClassKind;
|
||||||
|
import org.eclipse.cdt.core.parser.ast.IASTClassSpecifier;
|
||||||
|
import org.eclipse.cdt.core.search.ICSearchConstants;
|
||||||
|
import org.eclipse.cdt.internal.core.index.IDocument;
|
||||||
|
import org.eclipse.cdt.internal.core.index.IIndexer;
|
||||||
|
import org.eclipse.cdt.internal.core.index.IIndexerOutput;
|
||||||
|
import org.eclipse.cdt.internal.core.search.CharOperation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author bgheorgh
|
||||||
|
*/
|
||||||
|
|
||||||
|
public abstract class AbstractIndexer implements IIndexer, IIndexConstants, ICSearchConstants {
|
||||||
|
|
||||||
|
IIndexerOutput output;
|
||||||
|
final static int CLASS = 1;
|
||||||
|
final static int STRUCT = 2;
|
||||||
|
final static int UNION = 3;
|
||||||
|
|
||||||
|
public AbstractIndexer() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addClassSpecifier(IASTClassSpecifier classSpecification){
|
||||||
|
if (classSpecification.getClassKind().equals(ClassKind.CLASS))
|
||||||
|
{
|
||||||
|
this.output.addRef(encodeTypeEntry(classSpecification.getName().toCharArray(),CLASS));
|
||||||
|
}
|
||||||
|
else if (classSpecification.getClassKind().equals(ClassKind.STRUCT))
|
||||||
|
{
|
||||||
|
this.output.addRef(encodeTypeEntry(classSpecification.getName().toCharArray(),STRUCT));
|
||||||
|
}
|
||||||
|
else if (classSpecification.getClassKind().equals(ClassKind.UNION))
|
||||||
|
{
|
||||||
|
this.output.addRef(encodeTypeEntry(classSpecification.getName().toCharArray(),UNION));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addConstructorDeclaration(){
|
||||||
|
|
||||||
|
}
|
||||||
|
public void addConstructorReference(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addMemberDeclaration(){
|
||||||
|
|
||||||
|
}
|
||||||
|
public void addMemberReference(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addFunctionDeclaration(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addFunctionReference(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addNameReference(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addSuperTypeReference(int modifiers, char[] packageName, char[] typeName, char[][] enclosingTypeNames, char classOrInterface, char[] superTypeName, char superClassOrInterface){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addTypeReference(char[] typeName){
|
||||||
|
this.output.addRef(CharOperation.concat(TYPE_REF, CharOperation.lastSegment(typeName, '.')));
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Type entries are encoded as follow: 'typeDecl/' ('C' | 'S' | 'U' ) '/' TypeName '/'
|
||||||
|
*/
|
||||||
|
protected static final char[] encodeTypeEntry( char[] typeName, int classType) {
|
||||||
|
|
||||||
|
int pos;
|
||||||
|
//3 - 1 for SUFFIX letter, 2 Separators
|
||||||
|
char[] result = new char[TYPE_DECL_LENGTH + typeName.length + 3];
|
||||||
|
System.arraycopy(TYPE_DECL, 0, result, 0, pos = TYPE_DECL_LENGTH);
|
||||||
|
switch (classType)
|
||||||
|
{
|
||||||
|
case(CLASS):
|
||||||
|
result[pos++] = CLASS_SUFFIX;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case(STRUCT):
|
||||||
|
result[pos++] = STRUCT_SUFFIX;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case(UNION):
|
||||||
|
result[pos++] = UNION_SUFFIX;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
result[pos++] = SEPARATOR;
|
||||||
|
System.arraycopy(typeName, 0, result, pos, typeName.length);
|
||||||
|
pos += typeName.length;
|
||||||
|
result[pos++] = SEPARATOR;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Returns the file types the <code>IIndexer</code> handles.
|
||||||
|
*/
|
||||||
|
public abstract String[] getFileTypes();
|
||||||
|
/**
|
||||||
|
* @see IIndexer#index(IDocument document, IIndexerOutput output)
|
||||||
|
*/
|
||||||
|
public void index(IDocument document, IIndexerOutput output) throws IOException {
|
||||||
|
this.output = output;
|
||||||
|
if (shouldIndex(document)) indexFile(document);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void indexFile(IDocument document) throws IOException;
|
||||||
|
/**
|
||||||
|
* @see IIndexer#shouldIndex(IDocument document)
|
||||||
|
*/
|
||||||
|
public boolean shouldIndex(IDocument document) {
|
||||||
|
String type = document.getType();
|
||||||
|
String[] supportedTypes = this.getFileTypes();
|
||||||
|
for (int i = 0; i < supportedTypes.length; ++i) {
|
||||||
|
if (supportedTypes[i].equals(type))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2003 IBM Corporation and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Common Public License v0.5
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/cpl-v05.html
|
||||||
|
******************************************************************************/
|
||||||
|
/*
|
||||||
|
* Created on May 30, 2003
|
||||||
|
*/
|
||||||
|
package org.eclipse.cdt.internal.core.search.indexing;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.eclipse.core.resources.IFile;
|
||||||
|
import org.eclipse.core.runtime.IPath;
|
||||||
|
import org.eclipse.cdt.internal.core.index.IIndex;
|
||||||
|
import org.eclipse.cdt.internal.core.index.impl.IFileDocument;
|
||||||
|
|
||||||
|
public class AddCompilationUnitToIndex extends AddFileToIndex {
|
||||||
|
char[] contents;
|
||||||
|
|
||||||
|
public AddCompilationUnitToIndex(IFile resource, IPath indexedContainer, IndexManager manager) {
|
||||||
|
super(resource, indexedContainer, manager);
|
||||||
|
}
|
||||||
|
protected boolean indexDocument(IIndex index) throws IOException {
|
||||||
|
if (!initializeContents()) return false;
|
||||||
|
index.add(new IFileDocument(resource, this.contents), new SourceIndexer(resource));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
public boolean initializeContents() {
|
||||||
|
if (this.contents == null) {
|
||||||
|
try {
|
||||||
|
IPath location = resource.getLocation();
|
||||||
|
if (location != null)
|
||||||
|
this.contents = org.eclipse.cdt.internal.core.search.Util.getFileCharContent(location.toFile(), null);
|
||||||
|
} catch (IOException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this.contents != null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2003 IBM Corporation and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Common Public License v0.5
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/cpl-v05.html
|
||||||
|
******************************************************************************/
|
||||||
|
/*
|
||||||
|
* Created on May 30, 2003
|
||||||
|
*/
|
||||||
|
package org.eclipse.cdt.internal.core.search.indexing;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.eclipse.core.resources.IFile;
|
||||||
|
import org.eclipse.core.runtime.IPath;
|
||||||
|
import org.eclipse.core.runtime.IProgressMonitor;
|
||||||
|
import org.eclipse.cdt.internal.core.index.IIndex;
|
||||||
|
import org.eclipse.cdt.internal.core.search.processing.JobManager;
|
||||||
|
|
||||||
|
public abstract class AddFileToIndex extends IndexRequest {
|
||||||
|
IFile resource;
|
||||||
|
|
||||||
|
public AddFileToIndex(IFile resource, IPath indexPath, IndexManager manager) {
|
||||||
|
super(indexPath, manager);
|
||||||
|
this.resource = resource;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean execute(IProgressMonitor progressMonitor) {
|
||||||
|
if (progressMonitor != null && progressMonitor.isCanceled()) return true;
|
||||||
|
/* ensure no concurrent write access to index */
|
||||||
|
IIndex index = manager.getIndex(this.indexPath, true, /*reuse index file*/ true /*create if none*/);
|
||||||
|
if (index == null) return true;
|
||||||
|
ReadWriteMonitor monitor = manager.getMonitorFor(index);
|
||||||
|
if (monitor == null) return true; // index got deleted since acquired
|
||||||
|
try {
|
||||||
|
monitor.enterWrite(); // ask permission to write
|
||||||
|
if (!indexDocument(index)) return false;
|
||||||
|
} catch (IOException e) {
|
||||||
|
if (JobManager.VERBOSE) {
|
||||||
|
JobManager.verbose("-> failed to index " + this.resource + " because of the following exception:"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} finally {
|
||||||
|
monitor.exitWrite(); // free write lock
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract boolean indexDocument(IIndex index) throws IOException;
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "indexing " + this.resource.getFullPath(); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,92 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2003 IBM Corporation and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Common Public License v0.5
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/cpl-v05.html
|
||||||
|
******************************************************************************/
|
||||||
|
/*
|
||||||
|
* Created on Jun 1, 2003
|
||||||
|
*/
|
||||||
|
package org.eclipse.cdt.internal.core.search.indexing;
|
||||||
|
|
||||||
|
import org.eclipse.core.resources.IFile;
|
||||||
|
import org.eclipse.core.resources.IProject;
|
||||||
|
import org.eclipse.core.resources.IResource;
|
||||||
|
import org.eclipse.core.resources.IResourceProxy;
|
||||||
|
import org.eclipse.core.resources.IResourceProxyVisitor;
|
||||||
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
import org.eclipse.core.runtime.IPath;
|
||||||
|
import org.eclipse.core.runtime.IProgressMonitor;
|
||||||
|
import org.eclipse.cdt.internal.core.search.Util;
|
||||||
|
import org.eclipse.cdt.internal.core.index.IIndex;
|
||||||
|
import org.eclipse.cdt.internal.core.search.processing.JobManager;
|
||||||
|
|
||||||
|
class AddFolderToIndex extends IndexRequest {
|
||||||
|
IPath folderPath;
|
||||||
|
IProject project;
|
||||||
|
char[][] exclusionPattern;
|
||||||
|
|
||||||
|
public AddFolderToIndex(IPath folderPath, IProject project, char[][] exclusionPattern, IndexManager manager) {
|
||||||
|
super(project.getFullPath(), manager);
|
||||||
|
this.folderPath = folderPath;
|
||||||
|
this.project = project;
|
||||||
|
this.exclusionPattern = exclusionPattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean execute(IProgressMonitor progressMonitor) {
|
||||||
|
if (progressMonitor != null && progressMonitor.isCanceled()) return true;
|
||||||
|
if (!project.isAccessible()) return true; // nothing to do
|
||||||
|
IResource folder = this.project.getParent().findMember(this.folderPath);
|
||||||
|
if (folder == null || folder.getType() == IResource.FILE) return true; // nothing to do, source folder was removed
|
||||||
|
|
||||||
|
/* ensure no concurrent write access to index */
|
||||||
|
IIndex index = manager.getIndex(this.indexPath, true, /*reuse index file*/ true /*create if none*/);
|
||||||
|
if (index == null) return true;
|
||||||
|
ReadWriteMonitor monitor = manager.getMonitorFor(index);
|
||||||
|
if (monitor == null) return true; // index got deleted since acquired
|
||||||
|
|
||||||
|
try {
|
||||||
|
monitor.enterRead(); // ask permission to read
|
||||||
|
|
||||||
|
final IPath container = this.indexPath;
|
||||||
|
final IndexManager indexManager = this.manager;
|
||||||
|
final char[][] pattern = exclusionPattern;
|
||||||
|
folder.accept(
|
||||||
|
new IResourceProxyVisitor() {
|
||||||
|
public boolean visit(IResourceProxy proxy) throws CoreException {
|
||||||
|
switch(proxy.getType()) {
|
||||||
|
case IResource.FILE :
|
||||||
|
// TODO: BOG Put the file name checking back
|
||||||
|
//if (Util.isJavaFileName(proxy.getName())) {
|
||||||
|
IResource resource = proxy.requestResource();
|
||||||
|
if (pattern == null || !Util.isExcluded(resource, pattern))
|
||||||
|
indexManager.addSource((IFile)resource, container);
|
||||||
|
//}
|
||||||
|
//return false;
|
||||||
|
case IResource.FOLDER :
|
||||||
|
if (pattern != null && Util.isExcluded(proxy.requestResource(), pattern))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
IResource.NONE
|
||||||
|
);
|
||||||
|
} catch (CoreException e) {
|
||||||
|
if (JobManager.VERBOSE) {
|
||||||
|
JobManager.verbose("-> failed to add " + this.folderPath + " to index because of the following exception:"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} finally {
|
||||||
|
monitor.exitRead(); // free read lock
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "adding " + this.folderPath + " to index " + this.indexPath; //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2003 IBM Corporation and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Common Public License v0.5
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/cpl-v05.html
|
||||||
|
******************************************************************************/
|
||||||
|
/*
|
||||||
|
* Created on May 30, 2003
|
||||||
|
*/
|
||||||
|
package org.eclipse.cdt.internal.core.search.indexing;
|
||||||
|
/**
|
||||||
|
* @author bgheorgh
|
||||||
|
*/
|
||||||
|
public interface IIndexConstants {
|
||||||
|
|
||||||
|
/* index encoding */
|
||||||
|
char[] REF= "ref/".toCharArray(); //$NON-NLS-1$
|
||||||
|
|
||||||
|
char[] TYPE_REF= "typeRef/".toCharArray(); //$NON-NLS-1$
|
||||||
|
char[] TYPE_DECL = "typeDecl/".toCharArray(); //$NON-NLS-1$
|
||||||
|
int TYPE_DECL_LENGTH = 9;
|
||||||
|
|
||||||
|
char[] FUNCTION_REF= "functionRef/".toCharArray(); //$NON-NLS-1$
|
||||||
|
char[] FUNCTION_DECL= "functionDecl/".toCharArray(); //$NON-NLS-1$
|
||||||
|
|
||||||
|
char[] CONSTRUCTOR_REF= "constructorRef/".toCharArray(); //$NON-NLS-1$
|
||||||
|
char[] CONSTRUCTOR_DECL= "constructorDecl/".toCharArray(); //$NON-NLS-1$
|
||||||
|
|
||||||
|
char[] NAMESPACE_REF= "namespaceRef/".toCharArray(); //$NON-NLS-1$
|
||||||
|
char[] NAMESPACE_DECL= "namespaceDecl/".toCharArray(); //$NON-NLS-1$
|
||||||
|
|
||||||
|
char[] MEMBER_REF= "memberRef/".toCharArray(); //$NON-NLS-1$
|
||||||
|
char[] MEMBER_DECL= "memberDecl/".toCharArray(); //$NON-NLS-1$
|
||||||
|
|
||||||
|
//a Var REF will be treated as a typeREF
|
||||||
|
//char[] VAR_REF= "varRef/".toCharArray(); //$NON-NLS-1$
|
||||||
|
|
||||||
|
//a Struct REF will be treated as a typeREF
|
||||||
|
//char[] STRUCT_REF= "structRef/".toCharArray(); //$NON-NLS-1$
|
||||||
|
|
||||||
|
//a Enum REF will be treated as a typeREF
|
||||||
|
//char[] ENUM_REF= "enumRef/".toCharArray(); //$NON-NLS-1$
|
||||||
|
|
||||||
|
//a UNION REF will be treated as a typeREF
|
||||||
|
//char[] UNION_REF= "unionRef/".toCharArray(); //$NON-NLS-1$
|
||||||
|
|
||||||
|
|
||||||
|
char[] SUPER_REF = "superRef/".toCharArray(); //$NON-NLS-1$
|
||||||
|
|
||||||
|
char[] CLASS_DECL= "typeDecl/C/".toCharArray(); //$NON-NLS-1$
|
||||||
|
char[] VAR_DECL= "typeDecl/V/".toCharArray(); //$NON-NLS-1$
|
||||||
|
char[] STRUCT_DECL= "typeDecl/S/".toCharArray(); //$NON-NLS-1$
|
||||||
|
char[] ENUM_DECL= "typeDecl/E/".toCharArray(); //$NON-NLS-1$
|
||||||
|
char[] UNION_DECL= "typeDecl/U/".toCharArray(); //$NON-NLS-1$
|
||||||
|
|
||||||
|
char[] OBJECT = "Object".toCharArray(); //$NON-NLS-1$
|
||||||
|
char[][] COUNTS=
|
||||||
|
new char[][] { new char[] {'0'}, new char[] {'1'}, new char[] {'2'}, new char[] {'3'}, new char[] {'4'}, new char[] {'5'}, new char[] {'6'}, new char[] {'7'}, new char[] {'8'}, new char[] {'9'}
|
||||||
|
};
|
||||||
|
char CLASS_SUFFIX = 'C';
|
||||||
|
char VAR_SUFFIX = 'V';
|
||||||
|
char STRUCT_SUFFIX = 'S';
|
||||||
|
char ENUM_SUFFIX = 'E';
|
||||||
|
char UNION_SUFFIX = 'U';
|
||||||
|
|
||||||
|
char TYPE_SUFFIX = 0;
|
||||||
|
char SEPARATOR= '/';
|
||||||
|
|
||||||
|
char[] ONE_STAR = new char[] {'*'};
|
||||||
|
char[][] ONE_STAR_CHAR = new char[][] {ONE_STAR};
|
||||||
|
|
||||||
|
// used as special marker for enclosing type name of local and anonymous classes
|
||||||
|
char[] ONE_ZERO = new char[] {'0'};
|
||||||
|
char[][] ONE_ZERO_CHAR = new char[][] {ONE_ZERO};
|
||||||
|
}
|
|
@ -0,0 +1,214 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2003 IBM Corporation and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Common Public License v0.5
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/cpl-v05.html
|
||||||
|
******************************************************************************/
|
||||||
|
/*
|
||||||
|
* Created on Jun 1, 2003
|
||||||
|
*/
|
||||||
|
package org.eclipse.cdt.internal.core.search.indexing;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.HashSet;
|
||||||
|
|
||||||
|
import org.eclipse.core.resources.IFile;
|
||||||
|
import org.eclipse.core.resources.IProject;
|
||||||
|
import org.eclipse.core.resources.IResource;
|
||||||
|
import org.eclipse.core.resources.IResourceProxy;
|
||||||
|
import org.eclipse.core.resources.IResourceProxyVisitor;
|
||||||
|
import org.eclipse.core.resources.IWorkspaceRoot;
|
||||||
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
import org.eclipse.core.runtime.IPath;
|
||||||
|
import org.eclipse.core.runtime.IProgressMonitor;
|
||||||
|
import org.eclipse.cdt.core.model.ICProject;
|
||||||
|
import org.eclipse.cdt.internal.core.search.Util;
|
||||||
|
import org.eclipse.cdt.internal.core.index.IIndex;
|
||||||
|
import org.eclipse.cdt.internal.core.index.IQueryResult;
|
||||||
|
import org.eclipse.cdt.internal.core.index.impl.IFileDocument;
|
||||||
|
import org.eclipse.cdt.internal.core.search.processing.JobManager;
|
||||||
|
import org.eclipse.cdt.internal.core.search.SimpleLookupTable;
|
||||||
|
import org.eclipse.cdt.internal.core.model.CModel;
|
||||||
|
import org.eclipse.cdt.internal.core.model.CModelManager;
|
||||||
|
import org.eclipse.cdt.core.model.ICElement;
|
||||||
|
|
||||||
|
|
||||||
|
public class IndexAllProject extends IndexRequest {
|
||||||
|
IProject project;
|
||||||
|
|
||||||
|
public IndexAllProject(IProject project, IndexManager manager) {
|
||||||
|
super(project.getFullPath(), manager);
|
||||||
|
this.project = project;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (o instanceof IndexAllProject)
|
||||||
|
return this.project.equals(((IndexAllProject) o).project);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Ensure consistency of a project index. Need to walk all nested resources,
|
||||||
|
* and discover resources which have either been changed, added or deleted
|
||||||
|
* since the index was produced.
|
||||||
|
*/
|
||||||
|
public boolean execute(IProgressMonitor progressMonitor) {
|
||||||
|
|
||||||
|
if (progressMonitor != null && progressMonitor.isCanceled()) return true;
|
||||||
|
if (!project.isAccessible()) return true; // nothing to do
|
||||||
|
|
||||||
|
IIndex index = this.manager.getIndex(this.indexPath, true, /*reuse index file*/ true /*create if none*/);
|
||||||
|
if (index == null) return true;
|
||||||
|
ReadWriteMonitor monitor = this.manager.getMonitorFor(index);
|
||||||
|
if (monitor == null) return true; // index got deleted since acquired
|
||||||
|
|
||||||
|
try {
|
||||||
|
monitor.enterRead(); // ask permission to read
|
||||||
|
saveIfNecessary(index, monitor);
|
||||||
|
|
||||||
|
IQueryResult[] results = index.queryInDocumentNames(""); // all file names //$NON-NLS-1$
|
||||||
|
int max = results == null ? 0 : results.length;
|
||||||
|
final SimpleLookupTable indexedFileNames = new SimpleLookupTable(max == 0 ? 33 : max + 11);
|
||||||
|
final String OK = "OK"; //$NON-NLS-1$
|
||||||
|
final String DELETED = "DELETED"; //$NON-NLS-1$
|
||||||
|
for (int i = 0; i < max; i++)
|
||||||
|
indexedFileNames.put(results[i].getPath(), DELETED);
|
||||||
|
final long indexLastModified = max == 0 ? 0L : index.getIndexFile().lastModified();
|
||||||
|
|
||||||
|
CModel model = (CModel) CModelManager.getDefault().getCModel();
|
||||||
|
ICProject cProject = model.getCProject(project.getName());
|
||||||
|
ICElement[] kids = cProject.getChildren();
|
||||||
|
IPath cProjectPath = cProject.getPath();
|
||||||
|
|
||||||
|
IWorkspaceRoot root = this.project.getWorkspace().getRoot();
|
||||||
|
IResource sourceFolder = root.findMember(cProjectPath);
|
||||||
|
|
||||||
|
if (this.isCancelled) return false;
|
||||||
|
|
||||||
|
if (sourceFolder != null) {
|
||||||
|
|
||||||
|
// collect output locations if source is project (see http://bugs.eclipse.org/bugs/show_bug.cgi?id=32041)
|
||||||
|
final HashSet outputs = new HashSet();
|
||||||
|
|
||||||
|
final boolean hasOutputs = !outputs.isEmpty();
|
||||||
|
|
||||||
|
final char[][] patterns = null;
|
||||||
|
if (max == 0) {
|
||||||
|
sourceFolder.accept(
|
||||||
|
new IResourceProxyVisitor() {
|
||||||
|
public boolean visit(IResourceProxy proxy) {
|
||||||
|
if (isCancelled) return false;
|
||||||
|
switch(proxy.getType()) {
|
||||||
|
case IResource.FILE :
|
||||||
|
//TODO: BOG Put the file name checking back
|
||||||
|
//if (Util.isCCFileName(proxy.getName())) {
|
||||||
|
IResource resource = proxy.requestResource();
|
||||||
|
if (resource.getLocation() != null && (patterns == null || !Util.isExcluded(resource, patterns))) {
|
||||||
|
String name = new IFileDocument((IFile) resource).getName();
|
||||||
|
indexedFileNames.put(name, resource);
|
||||||
|
}
|
||||||
|
//}
|
||||||
|
// return false;
|
||||||
|
|
||||||
|
case IResource.FOLDER :
|
||||||
|
if (patterns != null && Util.isExcluded(proxy.requestResource(), patterns))
|
||||||
|
return false;
|
||||||
|
if (hasOutputs && outputs.contains(proxy.requestFullPath())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
IResource.NONE
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
sourceFolder.accept(
|
||||||
|
new IResourceProxyVisitor() {
|
||||||
|
public boolean visit(IResourceProxy proxy) {
|
||||||
|
if (isCancelled) return false;
|
||||||
|
switch(proxy.getType()) {
|
||||||
|
case IResource.FILE :
|
||||||
|
// TODO: BOG Put the file name checking back
|
||||||
|
//if (Util.isCCFileName(proxy.getName())) {
|
||||||
|
IResource resource = proxy.requestResource();
|
||||||
|
IPath path = resource.getLocation();
|
||||||
|
if (path != null && (patterns == null || !Util.isExcluded(resource, patterns))) {
|
||||||
|
String name = new IFileDocument((IFile) resource).getName();
|
||||||
|
indexedFileNames.put(name,
|
||||||
|
indexedFileNames.get(name) == null || indexLastModified < path.toFile().lastModified()
|
||||||
|
? (Object) resource
|
||||||
|
: (Object) OK);
|
||||||
|
}
|
||||||
|
//}
|
||||||
|
//return false;
|
||||||
|
case IResource.FOLDER :
|
||||||
|
if (patterns != null && Util.isExcluded(proxy.requestResource(), patterns))
|
||||||
|
return false;
|
||||||
|
if (hasOutputs && outputs.contains(proxy.requestFullPath())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
IResource.NONE
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Object[] names = indexedFileNames.keyTable;
|
||||||
|
Object[] values = indexedFileNames.valueTable;
|
||||||
|
boolean shouldSave = false;
|
||||||
|
for (int i = 0, length = names.length; i < length; i++) {
|
||||||
|
String name = (String) names[i];
|
||||||
|
if (name != null) {
|
||||||
|
if (this.isCancelled) return false;
|
||||||
|
|
||||||
|
Object value = values[i];
|
||||||
|
if (value != OK) {
|
||||||
|
shouldSave = true;
|
||||||
|
if (value == DELETED)
|
||||||
|
this.manager.remove(name, this.indexPath);
|
||||||
|
else
|
||||||
|
this.manager.addSource((IFile) value, this.indexPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// request to save index when all cus have been indexed
|
||||||
|
if (shouldSave)
|
||||||
|
this.manager.request(new SaveIndex(this.indexPath, this.manager));
|
||||||
|
|
||||||
|
} catch (CoreException e) {
|
||||||
|
if (JobManager.VERBOSE) {
|
||||||
|
JobManager.verbose("-> failed to index " + this.project + " because of the following exception:"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
this.manager.removeIndex(this.indexPath);
|
||||||
|
return false;
|
||||||
|
} catch (IOException e) {
|
||||||
|
if (JobManager.VERBOSE) {
|
||||||
|
JobManager.verbose("-> failed to index " + this.project + " because of the following exception:"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
this.manager.removeIndex(this.indexPath);
|
||||||
|
return false;
|
||||||
|
} finally {
|
||||||
|
monitor.exitRead(); // free read lock
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int hashCode() {
|
||||||
|
return this.project.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Integer updatedIndexState() {
|
||||||
|
return IndexManager.REBUILDING_STATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "indexing project " + this.project.getFullPath(); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,611 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2003 IBM Corporation and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Common Public License v0.5
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/cpl-v05.html
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Created on May 30, 2003
|
||||||
|
*/
|
||||||
|
package org.eclipse.cdt.internal.core.search.indexing;
|
||||||
|
|
||||||
|
import java.io.BufferedWriter;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileWriter;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.zip.CRC32;
|
||||||
|
|
||||||
|
import org.eclipse.core.resources.IFile;
|
||||||
|
import org.eclipse.core.resources.IProject;
|
||||||
|
import org.eclipse.core.resources.IWorkspace;
|
||||||
|
import org.eclipse.core.resources.ResourcesPlugin;
|
||||||
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
import org.eclipse.core.runtime.IPath;
|
||||||
|
import org.eclipse.core.runtime.QualifiedName;
|
||||||
|
import org.eclipse.cdt.internal.core.search.processing.JobManager;
|
||||||
|
import org.eclipse.cdt.internal.core.search.processing.IJob;
|
||||||
|
import org.eclipse.cdt.internal.core.search.SimpleLookupTable;
|
||||||
|
import org.eclipse.cdt.internal.core.search.CharOperation;
|
||||||
|
import org.eclipse.cdt.internal.core.index.IIndex;
|
||||||
|
import org.eclipse.cdt.internal.core.index.impl.Index;
|
||||||
|
import org.eclipse.cdt.internal.core.model.CProject;
|
||||||
|
import org.eclipse.cdt.core.CCorePlugin;
|
||||||
|
|
||||||
|
public class IndexManager extends JobManager implements IIndexConstants {
|
||||||
|
/* number of file contents in memory */
|
||||||
|
public static int MAX_FILES_IN_MEMORY = 0;
|
||||||
|
|
||||||
|
public IWorkspace workspace;
|
||||||
|
public SimpleLookupTable indexNames = new SimpleLookupTable();
|
||||||
|
private Map indexes = new HashMap(5);
|
||||||
|
|
||||||
|
/* read write monitors */
|
||||||
|
private Map monitors = new HashMap(5);
|
||||||
|
|
||||||
|
/* need to save ? */
|
||||||
|
private boolean needToSave = false;
|
||||||
|
private static final CRC32 checksumCalculator = new CRC32();
|
||||||
|
private IPath javaPluginLocation = null;
|
||||||
|
|
||||||
|
/* can only replace a current state if its less than the new one */
|
||||||
|
private SimpleLookupTable indexStates = null;
|
||||||
|
private File savedIndexNamesFile =
|
||||||
|
new File(getJavaPluginWorkingLocation().append("savedIndexNames.txt").toOSString()); //$NON-NLS-1$
|
||||||
|
public static Integer SAVED_STATE = new Integer(0);
|
||||||
|
public static Integer UPDATING_STATE = new Integer(1);
|
||||||
|
public static Integer UNKNOWN_STATE = new Integer(2);
|
||||||
|
public static Integer REBUILDING_STATE = new Integer(3);
|
||||||
|
|
||||||
|
public synchronized void aboutToUpdateIndex(IPath path, Integer newIndexState) {
|
||||||
|
// newIndexState is either UPDATING_STATE or REBUILDING_STATE
|
||||||
|
// must tag the index as inconsistent, in case we exit before the update job is started
|
||||||
|
String indexName = computeIndexName(path);
|
||||||
|
Object state = getIndexStates().get(indexName);
|
||||||
|
Integer currentIndexState = state == null ? UNKNOWN_STATE : (Integer) state;
|
||||||
|
if (currentIndexState.equals(REBUILDING_STATE)) return; // already rebuilding the index
|
||||||
|
|
||||||
|
int compare = newIndexState.compareTo(currentIndexState);
|
||||||
|
if (compare > 0) {
|
||||||
|
// so UPDATING_STATE replaces SAVED_STATE and REBUILDING_STATE replaces everything
|
||||||
|
updateIndexState(indexName, newIndexState);
|
||||||
|
} else if (compare < 0 && this.indexes.get(path) == null) {
|
||||||
|
// if already cached index then there is nothing more to do
|
||||||
|
rebuildIndex(indexName, path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Not at the moment...
|
||||||
|
* @param resource
|
||||||
|
* @param indexedContainer
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
public void addBinary(IFile resource, IPath indexedContainer){
|
||||||
|
if (JavaCore.getPlugin() == null) return;
|
||||||
|
AddClassFileToIndex job = new AddClassFileToIndex(resource, indexedContainer, this);
|
||||||
|
if (this.awaitingJobsCount() < MAX_FILES_IN_MEMORY) {
|
||||||
|
// reduces the chance that the file is open later on, preventing it from being deleted
|
||||||
|
if (!job.initializeContents()) return;
|
||||||
|
}
|
||||||
|
request(job);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Trigger addition of a resource to an index
|
||||||
|
* Note: the actual operation is performed in background
|
||||||
|
*/
|
||||||
|
public void addSource(IFile resource, IPath indexedContainer){
|
||||||
|
if (CCorePlugin.getDefault() == null) return;
|
||||||
|
AddCompilationUnitToIndex job = new AddCompilationUnitToIndex(resource, indexedContainer, this);
|
||||||
|
if (this.awaitingJobsCount() < MAX_FILES_IN_MEMORY) {
|
||||||
|
// reduces the chance that the file is open later on, preventing it from being deleted
|
||||||
|
if (!job.initializeContents()) return;
|
||||||
|
}
|
||||||
|
request(job);
|
||||||
|
}
|
||||||
|
|
||||||
|
String computeIndexName(IPath path) {
|
||||||
|
String name = (String) indexNames.get(path);
|
||||||
|
if (name == null) {
|
||||||
|
String pathString = path.toOSString();
|
||||||
|
checksumCalculator.reset();
|
||||||
|
checksumCalculator.update(pathString.getBytes());
|
||||||
|
String fileName = Long.toString(checksumCalculator.getValue()) + ".index"; //$NON-NLS-1$
|
||||||
|
if (VERBOSE)
|
||||||
|
JobManager.verbose("-> index name for " + pathString + " is " + fileName); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
name = getJavaPluginWorkingLocation().append(fileName).toOSString();
|
||||||
|
indexNames.put(path, name);
|
||||||
|
}
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Returns the index for a given project, according to the following algorithm:
|
||||||
|
* - if index is already in memory: answers this one back
|
||||||
|
* - if (reuseExistingFile) then read it and return this index and record it in memory
|
||||||
|
* - if (createIfMissing) then create a new empty index and record it in memory
|
||||||
|
*
|
||||||
|
* Warning: Does not check whether index is consistent (not being used)
|
||||||
|
*/
|
||||||
|
public synchronized IIndex getIndex(IPath path, boolean reuseExistingFile, boolean createIfMissing) {
|
||||||
|
// Path is already canonical per construction
|
||||||
|
IIndex index = (IIndex) indexes.get(path);
|
||||||
|
if (index == null) {
|
||||||
|
String indexName = computeIndexName(path);
|
||||||
|
Object state = getIndexStates().get(indexName);
|
||||||
|
Integer currentIndexState = state == null ? UNKNOWN_STATE : (Integer) state;
|
||||||
|
if (currentIndexState == UNKNOWN_STATE) {
|
||||||
|
// should only be reachable for query jobs
|
||||||
|
// IF you put an index in the cache, then AddJarFileToIndex fails because it thinks there is nothing to do
|
||||||
|
rebuildIndex(indexName, path);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// index isn't cached, consider reusing an existing index file
|
||||||
|
if (reuseExistingFile) {
|
||||||
|
File indexFile = new File(indexName);
|
||||||
|
if (indexFile.exists()) { // check before creating index so as to avoid creating a new empty index if file is missing
|
||||||
|
try {
|
||||||
|
index = new Index(indexName, "Index for " + path.toOSString(), true /*reuse index file*/); //$NON-NLS-1$
|
||||||
|
indexes.put(path, index);
|
||||||
|
monitors.put(index, new ReadWriteMonitor());
|
||||||
|
return index;
|
||||||
|
} catch (IOException e) {
|
||||||
|
// failed to read the existing file or its no longer compatible
|
||||||
|
if (currentIndexState != REBUILDING_STATE) { // rebuild index if existing file is corrupt, unless the index is already being rebuilt
|
||||||
|
if (VERBOSE)
|
||||||
|
JobManager.verbose("-> cannot reuse existing index: "+indexName+" path: "+path.toOSString()); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
rebuildIndex(indexName, path);
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
index = null; // will fall thru to createIfMissing & create a empty index for the rebuild all job to populate
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (currentIndexState == SAVED_STATE) { // rebuild index if existing file is missing
|
||||||
|
rebuildIndex(indexName, path);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// index wasn't found on disk, consider creating an empty new one
|
||||||
|
if (createIfMissing) {
|
||||||
|
try {
|
||||||
|
if (VERBOSE)
|
||||||
|
JobManager.verbose("-> create empty index: "+indexName+" path: "+path.toOSString()); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
index = new Index(indexName, "Index for " + path.toOSString(), false /*do not reuse index file*/); //$NON-NLS-1$
|
||||||
|
indexes.put(path, index);
|
||||||
|
monitors.put(index, new ReadWriteMonitor());
|
||||||
|
return index;
|
||||||
|
} catch (IOException e) {
|
||||||
|
if (VERBOSE)
|
||||||
|
JobManager.verbose("-> unable to create empty index: "+indexName+" path: "+path.toOSString()); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
// The file could not be created. Possible reason: the project has been deleted.
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//System.out.println(" index name: " + path.toOSString() + " <----> " + index.getIndexFile().getName());
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
private SimpleLookupTable getIndexStates() {
|
||||||
|
if (indexStates != null) return indexStates;
|
||||||
|
|
||||||
|
this.indexStates = new SimpleLookupTable();
|
||||||
|
char[] savedIndexNames = readIndexState();
|
||||||
|
if (savedIndexNames.length > 0) {
|
||||||
|
char[][] names = CharOperation.splitOn('\n', savedIndexNames);
|
||||||
|
for (int i = 0, l = names.length; i < l; i++) {
|
||||||
|
char[] name = names[i];
|
||||||
|
if (name.length > 0)
|
||||||
|
this.indexStates.put(new String(name), SAVED_STATE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this.indexStates;
|
||||||
|
}
|
||||||
|
|
||||||
|
private IPath getJavaPluginWorkingLocation() {
|
||||||
|
if (this.javaPluginLocation != null) return this.javaPluginLocation;
|
||||||
|
|
||||||
|
return this.javaPluginLocation = CCorePlugin.getDefault().getStateLocation();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Index access is controlled through a read-write monitor so as
|
||||||
|
* to ensure there is no concurrent read and write operations
|
||||||
|
* (only concurrent reading is allowed).
|
||||||
|
*/
|
||||||
|
public ReadWriteMonitor getMonitorFor(IIndex index){
|
||||||
|
return (ReadWriteMonitor) monitors.get(index);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Trigger addition of the entire content of a project
|
||||||
|
* Note: the actual operation is performed in background
|
||||||
|
*/
|
||||||
|
public void indexAll(IProject project) {
|
||||||
|
if (CCorePlugin.getDefault() == null) return;
|
||||||
|
|
||||||
|
/******
|
||||||
|
*TODO: Remove these methods once the new indexer is
|
||||||
|
*fully integrated
|
||||||
|
*/
|
||||||
|
if (!isEnabled(project)) return;
|
||||||
|
|
||||||
|
// check if the same request is not already in the queue
|
||||||
|
IndexRequest request = new IndexAllProject(project, this);
|
||||||
|
for (int i = this.jobEnd; i > this.jobStart; i--) // NB: don't check job at jobStart, as it may have already started (see http://bugs.eclipse.org/bugs/show_bug.cgi?id=32488)
|
||||||
|
if (request.equals(this.awaitingJobs[i])) return;
|
||||||
|
this.request(request);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Index the content of the given source folder.
|
||||||
|
*/
|
||||||
|
public void indexSourceFolder(CProject javaProject, IPath sourceFolder, final char[][] exclusionPattern) {
|
||||||
|
IProject project = javaProject.getProject();
|
||||||
|
if (this.jobEnd > this.jobStart) {
|
||||||
|
// check if a job to index the project is not already in the queue
|
||||||
|
IndexRequest request = new IndexAllProject(project, this);
|
||||||
|
for (int i = this.jobEnd; i > this.jobStart; i--) // NB: don't check job at jobStart, as it may have already started (see http://bugs.eclipse.org/bugs/show_bug.cgi?id=32488)
|
||||||
|
if (request.equals(this.awaitingJobs[i])) return;
|
||||||
|
}
|
||||||
|
this.request(new AddFolderToIndex(sourceFolder, project, exclusionPattern, this));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void jobWasCancelled(IPath path) {
|
||||||
|
Object o = this.indexes.get(path);
|
||||||
|
if (o instanceof IIndex) {
|
||||||
|
this.monitors.remove(o);
|
||||||
|
this.indexes.remove(path);
|
||||||
|
}
|
||||||
|
updateIndexState(computeIndexName(path), UNKNOWN_STATE);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Advance to the next available job, once the current one has been completed.
|
||||||
|
* Note: clients awaiting until the job count is zero are still waiting at this point.
|
||||||
|
*/
|
||||||
|
protected synchronized void moveToNextJob() {
|
||||||
|
// remember that one job was executed, and we will need to save indexes at some point
|
||||||
|
needToSave = true;
|
||||||
|
super.moveToNextJob();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* No more job awaiting.
|
||||||
|
*/
|
||||||
|
protected void notifyIdle(long idlingTime){
|
||||||
|
if (idlingTime > 1000 && needToSave) saveIndexes();
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* For debug purpose
|
||||||
|
*/
|
||||||
|
public IIndex peekAtIndex(IPath path) {
|
||||||
|
return (IIndex) indexes.get(path);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Name of the background process
|
||||||
|
*/
|
||||||
|
public String processName(){
|
||||||
|
return org.eclipse.cdt.internal.core.search.Util.bind("process.name"); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
|
||||||
|
private void rebuildIndex(String indexName, IPath path) {
|
||||||
|
Object target = org.eclipse.cdt.internal.core.search.Util.getTarget(ResourcesPlugin.getWorkspace().getRoot(), path, true);
|
||||||
|
if (target == null) return;
|
||||||
|
|
||||||
|
if (VERBOSE)
|
||||||
|
JobManager.verbose("-> request to rebuild index: "+indexName+" path: "+path.toOSString()); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
|
||||||
|
updateIndexState(indexName, REBUILDING_STATE);
|
||||||
|
IndexRequest request = null;
|
||||||
|
if (target instanceof IProject) {
|
||||||
|
IProject p = (IProject) target;
|
||||||
|
//if (JavaProject.hasJavaNature(p))
|
||||||
|
request = new IndexAllProject(p, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request != null)
|
||||||
|
request(request);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Recreates the index for a given path, keeping the same read-write monitor.
|
||||||
|
* Returns the new empty index or null if it didn't exist before.
|
||||||
|
* Warning: Does not check whether index is consistent (not being used)
|
||||||
|
*/
|
||||||
|
public synchronized IIndex recreateIndex(IPath path) {
|
||||||
|
// only called to over write an existing cached index...
|
||||||
|
try {
|
||||||
|
IIndex index = (IIndex) this.indexes.get(path);
|
||||||
|
ReadWriteMonitor monitor = (ReadWriteMonitor) this.monitors.remove(index);
|
||||||
|
|
||||||
|
// Path is already canonical
|
||||||
|
String indexPath = computeIndexName(path);
|
||||||
|
if (VERBOSE)
|
||||||
|
JobManager.verbose("-> recreating index: "+indexPath+" for path: "+path.toOSString()); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
index = new Index(indexPath, "Index for " + path.toOSString(), false /*reuse index file*/); //$NON-NLS-1$
|
||||||
|
indexes.put(path, index);
|
||||||
|
monitors.put(index, monitor);
|
||||||
|
return index;
|
||||||
|
} catch (IOException e) {
|
||||||
|
// The file could not be created. Possible reason: the project has been deleted.
|
||||||
|
if (VERBOSE) {
|
||||||
|
JobManager.verbose("-> failed to recreate index for path: "+path.toOSString()); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Trigger removal of a resource to an index
|
||||||
|
* Note: the actual operation is performed in background
|
||||||
|
*/
|
||||||
|
public void remove(String resourceName, IPath indexedContainer){
|
||||||
|
request(new RemoveFromIndex(resourceName, indexedContainer, this));
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Removes the index for a given path.
|
||||||
|
* This is a no-op if the index did not exist.
|
||||||
|
*/
|
||||||
|
public synchronized void removeIndex(IPath path) {
|
||||||
|
if (VERBOSE)
|
||||||
|
JobManager.verbose("removing index " + path); //$NON-NLS-1$
|
||||||
|
String indexName = computeIndexName(path);
|
||||||
|
File indexFile = new File(indexName);
|
||||||
|
if (indexFile.exists())
|
||||||
|
indexFile.delete();
|
||||||
|
Object o = this.indexes.get(path);
|
||||||
|
if (o instanceof IIndex)
|
||||||
|
this.monitors.remove(o);
|
||||||
|
this.indexes.remove(path);
|
||||||
|
updateIndexState(indexName, null);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Removes all indexes whose paths start with (or are equal to) the given path.
|
||||||
|
*/
|
||||||
|
public synchronized void removeIndexFamily(IPath path) {
|
||||||
|
// only finds cached index files... shutdown removes all non-cached index files
|
||||||
|
ArrayList toRemove = null;
|
||||||
|
Iterator iterator = this.indexes.keySet().iterator();
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
IPath indexPath = (IPath) iterator.next();
|
||||||
|
if (path.isPrefixOf(indexPath)) {
|
||||||
|
if (toRemove == null)
|
||||||
|
toRemove = new ArrayList();
|
||||||
|
toRemove.add(indexPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (toRemove != null)
|
||||||
|
for (int i = 0, length = toRemove.size(); i < length; i++)
|
||||||
|
this.removeIndex((IPath) toRemove.get(i));
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Remove the content of the given source folder from the index.
|
||||||
|
*/
|
||||||
|
public void removeSourceFolderFromIndex(CProject javaProject, IPath sourceFolder, char[][] exclusionPatterns) {
|
||||||
|
IProject project = javaProject.getProject();
|
||||||
|
if (this.jobEnd > this.jobStart) {
|
||||||
|
// check if a job to index the project is not already in the queue
|
||||||
|
IndexRequest request = new IndexAllProject(project, this);
|
||||||
|
for (int i = this.jobEnd; i > this.jobStart; i--) // NB: don't check job at jobStart, as it may have already started (see http://bugs.eclipse.org/bugs/show_bug.cgi?id=32488)
|
||||||
|
if (request.equals(this.awaitingJobs[i])) return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.request(new RemoveFolderFromIndex(sourceFolder, exclusionPatterns, project, this));
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Flush current state
|
||||||
|
*/
|
||||||
|
public void reset() {
|
||||||
|
super.reset();
|
||||||
|
if (this.indexes != null) {
|
||||||
|
this.indexes = new HashMap(5);
|
||||||
|
this.monitors = new HashMap(5);
|
||||||
|
this.indexStates = null;
|
||||||
|
}
|
||||||
|
this.indexNames = new SimpleLookupTable();
|
||||||
|
this.javaPluginLocation = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void saveIndex(IIndex index) throws IOException {
|
||||||
|
// must have permission to write from the write monitor
|
||||||
|
if (index.hasChanged()) {
|
||||||
|
if (VERBOSE)
|
||||||
|
JobManager.verbose("-> saving index " + index.getIndexFile()); //$NON-NLS-1$
|
||||||
|
index.save();
|
||||||
|
}
|
||||||
|
String indexName = index.getIndexFile().getPath();
|
||||||
|
if (this.jobEnd > this.jobStart) {
|
||||||
|
Object indexPath = indexNames.keyForValue(indexName);
|
||||||
|
if (indexPath != null) {
|
||||||
|
for (int i = this.jobEnd; i > this.jobStart; i--) { // skip the current job
|
||||||
|
IJob job = this.awaitingJobs[i];
|
||||||
|
if (job instanceof IndexRequest)
|
||||||
|
if (((IndexRequest) job).indexPath.equals(indexPath)) return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
updateIndexState(indexName, SAVED_STATE);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Commit all index memory changes to disk
|
||||||
|
*/
|
||||||
|
public void saveIndexes() {
|
||||||
|
// only save cached indexes... the rest were not modified
|
||||||
|
ArrayList toSave = new ArrayList();
|
||||||
|
synchronized(this) {
|
||||||
|
for (Iterator iter = this.indexes.values().iterator(); iter.hasNext();) {
|
||||||
|
Object o = iter.next();
|
||||||
|
if (o instanceof IIndex)
|
||||||
|
toSave.add(o);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0, length = toSave.size(); i < length; i++) {
|
||||||
|
IIndex index = (IIndex) toSave.get(i);
|
||||||
|
ReadWriteMonitor monitor = getMonitorFor(index);
|
||||||
|
if (monitor == null) continue; // index got deleted since acquired
|
||||||
|
try {
|
||||||
|
monitor.enterWrite();
|
||||||
|
try {
|
||||||
|
saveIndex(index);
|
||||||
|
} catch(IOException e){
|
||||||
|
if (VERBOSE) {
|
||||||
|
JobManager.verbose("-> got the following exception while saving:"); //$NON-NLS-1$
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
//Util.log(e);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
monitor.exitWrite();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
needToSave = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void shutdown() {
|
||||||
|
if (VERBOSE)
|
||||||
|
JobManager.verbose("Shutdown"); //$NON-NLS-1$
|
||||||
|
//TODO: BOG Put in Shutdown
|
||||||
|
/*
|
||||||
|
IndexSelector indexSelector = new IndexSelector(new JavaWorkspaceScope(), null, false, this);
|
||||||
|
IIndex[] selectedIndexes = indexSelector.getIndexes();
|
||||||
|
SimpleLookupTable knownPaths = new SimpleLookupTable();
|
||||||
|
for (int i = 0, max = selectedIndexes.length; i < max; i++) {
|
||||||
|
String path = selectedIndexes[i].getIndexFile().getAbsolutePath();
|
||||||
|
knownPaths.put(path, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (indexStates != null) {
|
||||||
|
Object[] indexNames = indexStates.keyTable;
|
||||||
|
for (int i = 0, l = indexNames.length; i < l; i++) {
|
||||||
|
String key = (String) indexNames[i];
|
||||||
|
if (key != null && !knownPaths.containsKey(key))
|
||||||
|
updateIndexState(key, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
File indexesDirectory = new File(getJavaPluginWorkingLocation().toOSString());
|
||||||
|
if (indexesDirectory.isDirectory()) {
|
||||||
|
File[] indexesFiles = indexesDirectory.listFiles();
|
||||||
|
if (indexesFiles != null) {
|
||||||
|
for (int i = 0, indexesFilesLength = indexesFiles.length; i < indexesFilesLength; i++) {
|
||||||
|
String fileName = indexesFiles[i].getAbsolutePath();
|
||||||
|
if (!knownPaths.containsKey(fileName) && fileName.toLowerCase().endsWith(".index")) { //$NON-NLS-1$
|
||||||
|
if (VERBOSE)
|
||||||
|
JobManager.verbose("Deleting index file " + indexesFiles[i]); //$NON-NLS-1$
|
||||||
|
indexesFiles[i].delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
super.shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
StringBuffer buffer = new StringBuffer(10);
|
||||||
|
buffer.append(super.toString());
|
||||||
|
buffer.append("In-memory indexes:\n"); //$NON-NLS-1$
|
||||||
|
int count = 0;
|
||||||
|
for (Iterator iter = this.indexes.values().iterator(); iter.hasNext();) {
|
||||||
|
buffer.append(++count).append(" - ").append(iter.next().toString()).append('\n'); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
return buffer.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private char[] readIndexState() {
|
||||||
|
try {
|
||||||
|
return org.eclipse.cdt.internal.core.search.Util.getFileCharContent(savedIndexNamesFile, null);
|
||||||
|
} catch (IOException ignored) {
|
||||||
|
if (VERBOSE)
|
||||||
|
JobManager.verbose("Failed to read saved index file names"); //$NON-NLS-1$
|
||||||
|
return new char[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateIndexState(String indexName, Integer indexState) {
|
||||||
|
getIndexStates(); // ensure the states are initialized
|
||||||
|
if (indexState != null) {
|
||||||
|
if (indexState.equals(indexStates.get(indexName))) return; // not changed
|
||||||
|
indexStates.put(indexName, indexState);
|
||||||
|
} else {
|
||||||
|
if (!indexStates.containsKey(indexName)) return; // did not exist anyway
|
||||||
|
indexStates.removeKey(indexName);
|
||||||
|
}
|
||||||
|
|
||||||
|
BufferedWriter writer = null;
|
||||||
|
try {
|
||||||
|
writer = new BufferedWriter(new FileWriter(savedIndexNamesFile));
|
||||||
|
Object[] indexNames = indexStates.keyTable;
|
||||||
|
Object[] states = indexStates.valueTable;
|
||||||
|
for (int i = 0, l = states.length; i < l; i++) {
|
||||||
|
if (states[i] == SAVED_STATE) {
|
||||||
|
writer.write((String) indexNames[i]);
|
||||||
|
writer.write('\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (IOException ignored) {
|
||||||
|
if (VERBOSE)
|
||||||
|
JobManager.verbose("Failed to write saved index file names"); //$NON-NLS-1$
|
||||||
|
} finally {
|
||||||
|
if (writer != null) {
|
||||||
|
try {
|
||||||
|
writer.close();
|
||||||
|
} catch (IOException e) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (VERBOSE) {
|
||||||
|
String state = "?"; //$NON-NLS-1$
|
||||||
|
if (indexState == SAVED_STATE) state = "SAVED"; //$NON-NLS-1$
|
||||||
|
else if (indexState == UPDATING_STATE) state = "UPDATING"; //$NON-NLS-1$
|
||||||
|
else if (indexState == UNKNOWN_STATE) state = "UNKNOWN"; //$NON-NLS-1$
|
||||||
|
else if (indexState == REBUILDING_STATE) state = "REBUILDING"; //$NON-NLS-1$
|
||||||
|
JobManager.verbose("-> index state updated to: " + state + " for: "+indexName); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************
|
||||||
|
*TODO: Remove these methods once the new indexer is
|
||||||
|
*fully integrated
|
||||||
|
* START OF TEMP INDEXER ENABLE SECTION
|
||||||
|
*/
|
||||||
|
final static String INDEX_MODEL_ID = CCorePlugin.PLUGIN_ID + ".newindexmodel";
|
||||||
|
final static String ACTIVATION = "enable";
|
||||||
|
|
||||||
|
static QualifiedName activationKey = new QualifiedName(INDEX_MODEL_ID, ACTIVATION);
|
||||||
|
|
||||||
|
public boolean isEnabled(IProject project) {
|
||||||
|
String prop = null;
|
||||||
|
try {
|
||||||
|
if (project != null) {
|
||||||
|
prop = project.getPersistentProperty(activationKey);
|
||||||
|
}
|
||||||
|
} catch (CoreException e) {
|
||||||
|
}
|
||||||
|
return ((prop != null) && prop.equalsIgnoreCase("true"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEnabled(IProject project, boolean on) {
|
||||||
|
try {
|
||||||
|
if (project != null) {
|
||||||
|
Boolean newValue = new Boolean(on);
|
||||||
|
Boolean oldValue = new Boolean(isEnabled(project));
|
||||||
|
if (!oldValue.equals(newValue)) {
|
||||||
|
project.setPersistentProperty(activationKey, newValue.toString());
|
||||||
|
if (on) {
|
||||||
|
indexAll(project);
|
||||||
|
} else {
|
||||||
|
//remove(project);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (CoreException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/************
|
||||||
|
* END OF TEMP INDEXER ENABLE SECTION
|
||||||
|
*/
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2003 IBM Corporation and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Common Public License v0.5
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/cpl-v05.html
|
||||||
|
******************************************************************************/
|
||||||
|
/*
|
||||||
|
* Created on May 30, 2003
|
||||||
|
*/
|
||||||
|
package org.eclipse.cdt.internal.core.search.indexing;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.internal.core.search.processing.IJob;
|
||||||
|
import org.eclipse.core.runtime.IPath;
|
||||||
|
import org.eclipse.cdt.internal.core.index.IIndex;
|
||||||
|
|
||||||
|
public abstract class IndexRequest implements IJob {
|
||||||
|
protected boolean isCancelled = false;
|
||||||
|
protected IPath indexPath;
|
||||||
|
protected IndexManager manager;
|
||||||
|
|
||||||
|
public IndexRequest(IPath indexPath, IndexManager manager) {
|
||||||
|
this.indexPath = indexPath;
|
||||||
|
this.manager = manager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean belongsTo(String projectName) {
|
||||||
|
return projectName.equals(this.indexPath.segment(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void cancel() {
|
||||||
|
this.manager.jobWasCancelled(this.indexPath);
|
||||||
|
this.isCancelled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isReadyToRun() {
|
||||||
|
// tag the index as inconsistent
|
||||||
|
this.manager.aboutToUpdateIndex(indexPath, updatedIndexState());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* This code is assumed to be invoked while monitor has read lock
|
||||||
|
*/
|
||||||
|
protected void saveIfNecessary(IIndex index, ReadWriteMonitor monitor) throws IOException {
|
||||||
|
/* if index has changed, commit these before querying */
|
||||||
|
if (index.hasChanged()) {
|
||||||
|
try {
|
||||||
|
monitor.exitRead(); // free read lock
|
||||||
|
monitor.enterWrite(); // ask permission to write
|
||||||
|
this.manager.saveIndex(index);
|
||||||
|
} finally {
|
||||||
|
monitor.exitWriteEnterRead(); // finished writing and reacquire read permission
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Integer updatedIndexState() {
|
||||||
|
return IndexManager.UPDATING_STATE;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,84 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2003 IBM Corporation and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Common Public License v0.5
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/cpl-v05.html
|
||||||
|
******************************************************************************/
|
||||||
|
/*
|
||||||
|
* Created on May 30, 2003
|
||||||
|
*/
|
||||||
|
package org.eclipse.cdt.internal.core.search.indexing;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Monitor ensuring no more than one writer working concurrently.
|
||||||
|
* Multiple readers are allowed to perform simultaneously.
|
||||||
|
*/
|
||||||
|
public class ReadWriteMonitor {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <0 : writing (cannot go beyond -1, i.e one concurrent writer)
|
||||||
|
* =0 : idle
|
||||||
|
* >0 : reading (number of concurrent readers)
|
||||||
|
*/
|
||||||
|
private int status = 0;
|
||||||
|
/**
|
||||||
|
* Concurrent reading is allowed
|
||||||
|
* Blocking only when already writing.
|
||||||
|
*/
|
||||||
|
public synchronized void enterRead() {
|
||||||
|
|
||||||
|
while (status < 0){
|
||||||
|
try {
|
||||||
|
wait();
|
||||||
|
} catch(InterruptedException e){
|
||||||
|
}
|
||||||
|
}
|
||||||
|
status++;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Only one writer at a time is allowed to perform
|
||||||
|
* Blocking only when already writing or reading.
|
||||||
|
*/
|
||||||
|
public synchronized void enterWrite() {
|
||||||
|
|
||||||
|
while (status != 0){
|
||||||
|
try {
|
||||||
|
wait();
|
||||||
|
} catch(InterruptedException e){
|
||||||
|
}
|
||||||
|
}
|
||||||
|
status--;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Only notify waiting writer(s) if last reader
|
||||||
|
*/
|
||||||
|
public synchronized void exitRead() {
|
||||||
|
if (--status == 0) notifyAll();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* When writing is over, all readers and possible
|
||||||
|
* writers are granted permission to restart concurrently
|
||||||
|
*/
|
||||||
|
public synchronized void exitWrite() {
|
||||||
|
if (++status == 0) notifyAll();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Atomic exitWrite/enterRead: Allows to keep monitor in between
|
||||||
|
* exit write and next enter read.
|
||||||
|
* When writing is over, all readers are granted permissing to restart
|
||||||
|
* concurrently.
|
||||||
|
* This is the same as:
|
||||||
|
* <pre>
|
||||||
|
* synchronized(monitor) {
|
||||||
|
* monitor.exitWrite();
|
||||||
|
* monitor.enterRead();
|
||||||
|
* }
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
public synchronized void exitWriteEnterRead() {
|
||||||
|
this.exitWrite();
|
||||||
|
this.enterRead();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2003 IBM Corporation and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Common Public License v0.5
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/cpl-v05.html
|
||||||
|
******************************************************************************/
|
||||||
|
/*
|
||||||
|
* Created on Jun 1, 2003
|
||||||
|
*/
|
||||||
|
package org.eclipse.cdt.internal.core.search.indexing;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.eclipse.core.resources.IProject;
|
||||||
|
import org.eclipse.core.runtime.IPath;
|
||||||
|
import org.eclipse.core.runtime.IProgressMonitor;
|
||||||
|
import org.eclipse.core.runtime.Path;
|
||||||
|
import org.eclipse.cdt.internal.core.search.Util;
|
||||||
|
import org.eclipse.cdt.internal.core.index.IIndex;
|
||||||
|
import org.eclipse.cdt.internal.core.index.IQueryResult;
|
||||||
|
import org.eclipse.cdt.internal.core.search.processing.JobManager;
|
||||||
|
|
||||||
|
class RemoveFolderFromIndex extends IndexRequest {
|
||||||
|
IPath folderPath;
|
||||||
|
char[][] exclusionPatterns;
|
||||||
|
IProject project;
|
||||||
|
|
||||||
|
public RemoveFolderFromIndex(IPath folderPath, char[][] exclusionPatterns, IProject project, IndexManager manager) {
|
||||||
|
super(project.getFullPath(), manager);
|
||||||
|
this.folderPath = folderPath;
|
||||||
|
this.exclusionPatterns = exclusionPatterns;
|
||||||
|
this.project = project;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean execute(IProgressMonitor progressMonitor) {
|
||||||
|
if (progressMonitor != null && progressMonitor.isCanceled()) return true;
|
||||||
|
|
||||||
|
/* ensure no concurrent write access to index */
|
||||||
|
IIndex index = manager.getIndex(this.indexPath, true, /*reuse index file*/ false /*create if none*/);
|
||||||
|
if (index == null) return true;
|
||||||
|
ReadWriteMonitor monitor = manager.getMonitorFor(index);
|
||||||
|
if (monitor == null) return true; // index got deleted since acquired
|
||||||
|
|
||||||
|
try {
|
||||||
|
monitor.enterRead(); // ask permission to read
|
||||||
|
IQueryResult[] results = index.queryInDocumentNames(this.folderPath.toString());
|
||||||
|
// all file names belonging to the folder or its subfolders and that are not excluded (see http://bugs.eclipse.org/bugs/show_bug.cgi?id=32607)
|
||||||
|
for (int i = 0, max = results == null ? 0 : results.length; i < max; i++) {
|
||||||
|
String documentPath = results[i].getPath();
|
||||||
|
if (this.exclusionPatterns == null || !Util.isExcluded(new Path(documentPath), this.exclusionPatterns)) {
|
||||||
|
manager.remove(documentPath, this.indexPath); // write lock will be acquired by the remove operation
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
if (JobManager.VERBOSE) {
|
||||||
|
JobManager.verbose("-> failed to remove " + this.folderPath + " from index because of the following exception:"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} finally {
|
||||||
|
monitor.exitRead(); // free read lock
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "removing " + this.folderPath + " from index " + this.indexPath; //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2003 IBM Corporation and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Common Public License v0.5
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/cpl-v05.html
|
||||||
|
******************************************************************************/
|
||||||
|
/*
|
||||||
|
* Created on Jun 1, 2003
|
||||||
|
*/
|
||||||
|
package org.eclipse.cdt.internal.core.search.indexing;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.eclipse.core.runtime.IPath;
|
||||||
|
import org.eclipse.core.runtime.IProgressMonitor;
|
||||||
|
import org.eclipse.cdt.internal.core.index.IIndex;
|
||||||
|
import org.eclipse.cdt.internal.core.search.processing.JobManager;
|
||||||
|
|
||||||
|
class RemoveFromIndex extends IndexRequest {
|
||||||
|
String resourceName;
|
||||||
|
|
||||||
|
public RemoveFromIndex(String resourceName, IPath indexPath, IndexManager manager) {
|
||||||
|
super(indexPath, manager);
|
||||||
|
this.resourceName = resourceName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean execute(IProgressMonitor progressMonitor) {
|
||||||
|
|
||||||
|
if (progressMonitor != null && progressMonitor.isCanceled()) return true;
|
||||||
|
|
||||||
|
/* ensure no concurrent write access to index */
|
||||||
|
IIndex index = manager.getIndex(this.indexPath, true, /*reuse index file*/ false /*create if none*/);
|
||||||
|
if (index == null) return true;
|
||||||
|
ReadWriteMonitor monitor = manager.getMonitorFor(index);
|
||||||
|
if (monitor == null) return true; // index got deleted since acquired
|
||||||
|
|
||||||
|
try {
|
||||||
|
monitor.enterWrite(); // ask permission to write
|
||||||
|
index.remove(resourceName);
|
||||||
|
} catch (IOException e) {
|
||||||
|
if (JobManager.VERBOSE) {
|
||||||
|
JobManager.verbose("-> failed to remove " + this.resourceName + " from index because of the following exception:"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} finally {
|
||||||
|
monitor.exitWrite(); // free write lock
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "removing " + this.resourceName + " from index " + this.indexPath; //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2003 IBM Corporation and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Common Public License v0.5
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/cpl-v05.html
|
||||||
|
******************************************************************************/
|
||||||
|
/*
|
||||||
|
* Created on Jun 1, 2003
|
||||||
|
*/
|
||||||
|
package org.eclipse.cdt.internal.core.search.indexing;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.eclipse.core.runtime.IPath;
|
||||||
|
import org.eclipse.core.runtime.IProgressMonitor;
|
||||||
|
import org.eclipse.cdt.internal.core.index.IIndex;
|
||||||
|
import org.eclipse.cdt.internal.core.search.processing.JobManager;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Save the index of a project.
|
||||||
|
*/
|
||||||
|
public class SaveIndex extends IndexRequest {
|
||||||
|
public SaveIndex(IPath indexPath, IndexManager manager) {
|
||||||
|
super(indexPath, manager);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean execute(IProgressMonitor progressMonitor) {
|
||||||
|
if (progressMonitor != null && progressMonitor.isCanceled()) return true;
|
||||||
|
|
||||||
|
/* ensure no concurrent write access to index */
|
||||||
|
IIndex index = this.manager.getIndex(this.indexPath, true /*reuse index file*/, false /*don't create if none*/);
|
||||||
|
if (index == null) return true;
|
||||||
|
ReadWriteMonitor monitor = this.manager.getMonitorFor(index);
|
||||||
|
if (monitor == null) return true; // index got deleted since acquired
|
||||||
|
|
||||||
|
try {
|
||||||
|
monitor.enterWrite(); // ask permission to write
|
||||||
|
this.manager.saveIndex(index);
|
||||||
|
} catch (IOException e) {
|
||||||
|
if (JobManager.VERBOSE) {
|
||||||
|
JobManager.verbose("-> failed to save index " + this.indexPath + " because of the following exception:"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} finally {
|
||||||
|
monitor.exitWrite(); // free write lock
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "saving index for " + this.indexPath; //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,75 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2003 IBM Corporation and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Common Public License v0.5
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/cpl-v05.html
|
||||||
|
******************************************************************************/
|
||||||
|
/*
|
||||||
|
* Created on Jun 1, 2003
|
||||||
|
*/
|
||||||
|
package org.eclipse.cdt.internal.core.search.indexing;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author bgheorgh
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.StringReader;
|
||||||
|
|
||||||
|
import org.eclipse.core.resources.IFile;
|
||||||
|
import org.eclipse.cdt.core.parser.IParser;
|
||||||
|
import org.eclipse.cdt.core.parser.ParserFactory;
|
||||||
|
import org.eclipse.cdt.core.parser.ParserMode;
|
||||||
|
import org.eclipse.cdt.internal.core.index.IDocument;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A SourceIndexer indexes source files using the parser. The following items are indexed:
|
||||||
|
* Declarations:
|
||||||
|
* - Classes
|
||||||
|
* - Structs
|
||||||
|
* - Unions
|
||||||
|
* References:
|
||||||
|
* - Classes
|
||||||
|
* - Structs
|
||||||
|
* - Unions
|
||||||
|
*/
|
||||||
|
public class SourceIndexer extends AbstractIndexer {
|
||||||
|
|
||||||
|
//TODO: Indexer, add additional file types
|
||||||
|
public static final String[] FILE_TYPES= new String[] {"cpp","h"}; //$NON-NLS-1$
|
||||||
|
//protected DefaultProblemFactory problemFactory= new DefaultProblemFactory(Locale.getDefault());
|
||||||
|
IFile resourceFile;
|
||||||
|
|
||||||
|
SourceIndexer(IFile resourceFile) {
|
||||||
|
this.resourceFile = resourceFile;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Returns the file types the <code>IIndexer</code> handles.
|
||||||
|
*/
|
||||||
|
public String[] getFileTypes(){
|
||||||
|
return FILE_TYPES;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void indexFile(IDocument document) throws IOException {
|
||||||
|
// Add the name of the file to the index
|
||||||
|
output.addDocument(document);
|
||||||
|
// Create a new Parser
|
||||||
|
SourceIndexerRequestor requestor = new SourceIndexerRequestor(this, document);
|
||||||
|
IParser parser = ParserFactory.createParser(
|
||||||
|
ParserFactory.createScanner( new StringReader( document.getStringContent() ), document.getName(), null, null, ParserMode.QUICK_PARSE ),
|
||||||
|
requestor, ParserMode.QUICK_PARSE);
|
||||||
|
try{
|
||||||
|
parser.parse();
|
||||||
|
}
|
||||||
|
catch( Exception e ){
|
||||||
|
System.out.println( "Parse Exception in SourceIndexer" );
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Sets the document types the <code>IIndexer</code> handles.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public void setFileTypes(String[] fileTypes){}
|
||||||
|
}
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,16 @@
|
||||||
|
###############################################################################
|
||||||
|
# Copyright (c) 2000, 2003 IBM Corporation and others.
|
||||||
|
# All rights reserved. This program and the accompanying materials
|
||||||
|
# are made available under the terms of the Common Public License v1.0
|
||||||
|
# which accompanies this distribution, and is available at
|
||||||
|
# http://www.eclipse.org/legal/cpl-v10.html
|
||||||
|
#
|
||||||
|
# Contributors:
|
||||||
|
# IBM Corporation - initial API and implementation
|
||||||
|
###############################################################################
|
||||||
|
### Eclipse CDT Core Search messages.
|
||||||
|
|
||||||
|
engine.searching = Searching...
|
||||||
|
exception.wrongFormat = Wrong format
|
||||||
|
process.name = CDT Indexer
|
||||||
|
manager.filesToIndex = {0} files to index
|
|
@ -8,6 +8,7 @@ package org.eclipse.cdt.core.model;
|
||||||
import org.eclipse.cdt.core.CCorePlugin;
|
import org.eclipse.cdt.core.CCorePlugin;
|
||||||
import org.eclipse.cdt.internal.core.model.BatchOperation;
|
import org.eclipse.cdt.internal.core.model.BatchOperation;
|
||||||
import org.eclipse.cdt.internal.core.model.CModelManager;
|
import org.eclipse.cdt.internal.core.model.CModelManager;
|
||||||
|
import org.eclipse.cdt.internal.core.search.indexing.IndexManager;
|
||||||
import org.eclipse.core.resources.IFile;
|
import org.eclipse.core.resources.IFile;
|
||||||
import org.eclipse.core.resources.IFolder;
|
import org.eclipse.core.resources.IFolder;
|
||||||
import org.eclipse.core.resources.IProject;
|
import org.eclipse.core.resources.IProject;
|
||||||
|
@ -215,4 +216,14 @@ public class CoreModel {
|
||||||
workspace.run(new BatchOperation(action), monitor);
|
workspace.run(new BatchOperation(action), monitor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void startIndexing()
|
||||||
|
{
|
||||||
|
manager.getIndexManager().reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IndexManager getIndexManager(){
|
||||||
|
return manager.getIndexManager();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,7 @@ import org.eclipse.core.resources.ResourcesPlugin;
|
||||||
import org.eclipse.core.runtime.CoreException;
|
import org.eclipse.core.runtime.CoreException;
|
||||||
import org.eclipse.core.runtime.IPath;
|
import org.eclipse.core.runtime.IPath;
|
||||||
import org.eclipse.core.runtime.IProgressMonitor;
|
import org.eclipse.core.runtime.IProgressMonitor;
|
||||||
|
import org.eclipse.cdt.internal.core.search.indexing.IndexManager;
|
||||||
|
|
||||||
public class CModelManager implements IResourceChangeListener {
|
public class CModelManager implements IResourceChangeListener {
|
||||||
|
|
||||||
|
@ -755,4 +756,8 @@ public class CModelManager implements IResourceChangeListener {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IndexManager getIndexManager() {
|
||||||
|
return this.fDeltaProcessor.indexManager;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,8 @@ import org.eclipse.core.resources.IResource;
|
||||||
import org.eclipse.core.resources.IResourceDelta;
|
import org.eclipse.core.resources.IResourceDelta;
|
||||||
import org.eclipse.core.runtime.IPath;
|
import org.eclipse.core.runtime.IPath;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.internal.core.search.indexing.IndexManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class is used by <code>CModelManager</code> to convert
|
* This class is used by <code>CModelManager</code> to convert
|
||||||
* <code>IResourceDelta</code>s into <code>ICElementDelta</code>s.
|
* <code>IResourceDelta</code>s into <code>ICElementDelta</code>s.
|
||||||
|
@ -32,6 +34,8 @@ public class DeltaProcessor {
|
||||||
*/
|
*/
|
||||||
protected CElementDelta fCurrentDelta;
|
protected CElementDelta fCurrentDelta;
|
||||||
|
|
||||||
|
protected IndexManager indexManager = new IndexManager();
|
||||||
|
|
||||||
/* The C element that was last created (see createElement(IResource).
|
/* The C element that was last created (see createElement(IResource).
|
||||||
* This is used as a stack of C elements (using getParent() to pop it, and
|
* This is used as a stack of C elements (using getParent() to pop it, and
|
||||||
* using the various get*(...) to push it. */
|
* using the various get*(...) to push it. */
|
||||||
|
@ -333,6 +337,7 @@ public class DeltaProcessor {
|
||||||
// get the workspace delta, and start processing there.
|
// get the workspace delta, and start processing there.
|
||||||
IResourceDelta[] deltas = changes.getAffectedChildren();
|
IResourceDelta[] deltas = changes.getAffectedChildren();
|
||||||
ICElementDelta[] translatedDeltas = new CElementDelta[deltas.length];
|
ICElementDelta[] translatedDeltas = new CElementDelta[deltas.length];
|
||||||
|
System.out.println("delta.length: " + deltas.length);
|
||||||
for (int i = 0; i < deltas.length; i++) {
|
for (int i = 0; i < deltas.length; i++) {
|
||||||
IResourceDelta delta = deltas[i];
|
IResourceDelta delta = deltas[i];
|
||||||
fCurrentDelta = new CElementDelta(root);
|
fCurrentDelta = new CElementDelta(root);
|
||||||
|
@ -446,9 +451,37 @@ public class DeltaProcessor {
|
||||||
|
|
||||||
protected void updateIndexAddResource(ICElement element, IResourceDelta delta) {
|
protected void updateIndexAddResource(ICElement element, IResourceDelta delta) {
|
||||||
//CModelManager.getDefault().getIndexManager().addResource(delta.getResource());
|
//CModelManager.getDefault().getIndexManager().addResource(delta.getResource());
|
||||||
|
|
||||||
|
if (indexManager == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch (element.getElementType()) {
|
||||||
|
case ICElement.C_PROJECT :
|
||||||
|
this.indexManager.indexAll(element.getCProject().getProject());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void updateIndexRemoveResource(ICElement element, IResourceDelta delta) {
|
protected void updateIndexRemoveResource(ICElement element, IResourceDelta delta) {
|
||||||
//CModelManager.getDefault().getIndexManager().removeResource(delta.getResource());
|
//CModelManager.getDefault().getIndexManager().removeResource(delta.getResource());
|
||||||
|
|
||||||
|
/*
|
||||||
|
if (indexManager == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch (element.getElementType()) {
|
||||||
|
case ICElement.C_PROJECT :
|
||||||
|
this.indexManager.removeIndexFamily(element.getCProject().getProject().getFullPath());
|
||||||
|
// NB: Discarding index jobs belonging to this project was done during PRE_DELETE
|
||||||
|
break;
|
||||||
|
// NB: Update of index if project is opened, closed, or its java nature is added or removed
|
||||||
|
// is done in updateCurrentDeltaAndIndex
|
||||||
|
|
||||||
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
10
core/org.eclipse.cdt.core/search/ChangeLog
Normal file
10
core/org.eclipse.cdt.core/search/ChangeLog
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
2003-06-25 Bogdan Gheorghe
|
||||||
|
|
||||||
|
Modified:
|
||||||
|
|
||||||
|
* search/org/eclipse/cdt/core/search/ICSearchConstants.java
|
||||||
|
* search/org/eclipse/cdt/internal/core/search/Utils.java
|
||||||
|
- moved to index/org/eclipse/cdt/internal/core/search/Utils.java
|
||||||
|
* search/org/eclipse/cdt/internal/core/search/matching/CSearchPattern.java
|
||||||
|
* search/org/eclipse/cdt/internal/core/search/processing/IJob.java
|
||||||
|
* search/org/eclipse/cdt/internal/core/search/processing/JobManager.java
|
|
@ -9,15 +9,24 @@
|
||||||
* IBM Corp. - Rational Software - initial implementation
|
* IBM Corp. - Rational Software - initial implementation
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
/*
|
/*
|
||||||
* Created on Jun 11, 2003
|
* Created on May 31, 2003
|
||||||
*/
|
*/
|
||||||
package org.eclipse.cdt.core.search;
|
package org.eclipse.cdt.core.search;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author aniefer
|
* @author bgheorgh
|
||||||
*
|
*/
|
||||||
* To change the template for this generated type comment go to
|
import org.eclipse.cdt.internal.core.search.processing.*;
|
||||||
* Window>Preferences>Java>Code Generation>Code and Comments
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* This interface defines the constants used by the search engine.
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* This interface declares constants only; it is not intended to be implemented.
|
||||||
|
* </p>
|
||||||
|
* @see org.eclipse.cdt.core.search.SearchEngine
|
||||||
*/
|
*/
|
||||||
public interface ICSearchConstants {
|
public interface ICSearchConstants {
|
||||||
/**
|
/**
|
||||||
|
@ -34,36 +43,55 @@ public interface ICSearchConstants {
|
||||||
int TYPE= 0;
|
int TYPE= 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The searched element is a method.
|
* The searched element is a function.
|
||||||
*/
|
*/
|
||||||
int METHOD= 1;
|
int FUNCTION= 1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The searched element is a package.
|
* The searched element is a namespace.
|
||||||
*/
|
*/
|
||||||
//int PACKAGE= 2;
|
int NAMESPACE= 2;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The searched element is a constructor.
|
* The searched element is a constructor.
|
||||||
*/
|
*/
|
||||||
int CONSTRUCTOR= 2;
|
int CONSTRUCTOR= 3;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The searched element is a field.
|
* The searched element is a member.
|
||||||
|
*/
|
||||||
|
int MEMBER= 4;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The searched element is a variable.
|
||||||
|
* More selective than using TYPE
|
||||||
*/
|
*/
|
||||||
int FIELD= 3;
|
int VAR= 5;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The searched element is a class.
|
* The searched element is a class.
|
||||||
* More selective than using TYPE
|
* More selective than using TYPE
|
||||||
*/
|
*/
|
||||||
int CLASS= 4;
|
int CLASS= 6;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The searched element is an interface.
|
* The searched element is a struct.
|
||||||
* More selective than using TYPE
|
* More selective than using TYPE
|
||||||
*/
|
*/
|
||||||
int INTERFACE= 5;
|
int STRUCT= 7;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The searched element is a enum.
|
||||||
|
* More selective than using TYPE
|
||||||
|
*/
|
||||||
|
int ENUM= 8;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The searched element is a union.
|
||||||
|
* More selective than using TYPE
|
||||||
|
*/
|
||||||
|
int UNION= 9;
|
||||||
|
|
||||||
|
|
||||||
/* Nature of match */
|
/* Nature of match */
|
||||||
|
|
||||||
|
@ -81,7 +109,7 @@ public interface ICSearchConstants {
|
||||||
* rather exclusively search for classes implementing an interface, or interfaces
|
* rather exclusively search for classes implementing an interface, or interfaces
|
||||||
* extending an interface.
|
* extending an interface.
|
||||||
*/
|
*/
|
||||||
int IMPLEMENTORS= 1;
|
int DEFINITIONS= 1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The search result is a reference.
|
* The search result is a reference.
|
||||||
|
@ -100,23 +128,6 @@ public interface ICSearchConstants {
|
||||||
*/
|
*/
|
||||||
int ALL_OCCURRENCES= 3;
|
int ALL_OCCURRENCES= 3;
|
||||||
|
|
||||||
/**
|
|
||||||
* When searching for field matches, it will exclusively find read accesses, as
|
|
||||||
* opposed to write accesses. Note that some expressions are considered both
|
|
||||||
* as field read/write accesses: for example, x++; x+= 1;
|
|
||||||
*
|
|
||||||
* @since 2.0
|
|
||||||
*/
|
|
||||||
int READ_ACCESSES = 4;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* When searching for field matches, it will exclusively find write accesses, as
|
|
||||||
* opposed to read accesses. Note that some expressions are considered both
|
|
||||||
* as field read/write accesses: for example, x++; x+= 1;
|
|
||||||
*
|
|
||||||
* @since 2.0
|
|
||||||
*/
|
|
||||||
int WRITE_ACCESSES = 5;
|
|
||||||
|
|
||||||
/* Syntactic match modes */
|
/* Syntactic match modes */
|
||||||
|
|
||||||
|
@ -156,17 +167,17 @@ public interface ICSearchConstants {
|
||||||
* has not finished indexing the workspace. Results will more likely
|
* has not finished indexing the workspace. Results will more likely
|
||||||
* not contain all the matches.
|
* not contain all the matches.
|
||||||
*/
|
*/
|
||||||
//int FORCE_IMMEDIATE_SEARCH = IJob.ForceImmediate;
|
int FORCE_IMMEDIATE_SEARCH = IJob.ForceImmediate;
|
||||||
/**
|
/**
|
||||||
* The search operation throws an <code>org.eclipse.core.runtime.OperationCanceledException</code>
|
* The search operation throws an <code>org.eclipse.core.runtime.OperationCanceledException</code>
|
||||||
* if the underlying indexer has not finished indexing the workspace.
|
* if the underlying indexer has not finished indexing the workspace.
|
||||||
*/
|
*/
|
||||||
//int CANCEL_IF_NOT_READY_TO_SEARCH = IJob.CancelIfNotReady;
|
int CANCEL_IF_NOT_READY_TO_SEARCH = IJob.CancelIfNotReady;
|
||||||
/**
|
/**
|
||||||
* The search operation waits for the underlying indexer to finish indexing
|
* The search operation waits for the underlying indexer to finish indexing
|
||||||
* the workspace before starting the search.
|
* the workspace before starting the search.
|
||||||
*/
|
*/
|
||||||
//int WAIT_UNTIL_READY_TO_SEARCH = IJob.WaitUntilReady;
|
int WAIT_UNTIL_READY_TO_SEARCH = IJob.WaitUntilReady;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,41 +0,0 @@
|
||||||
/*******************************************************************************
|
|
||||||
* Copyright (c) 2003 IBM Corporation and others.
|
|
||||||
* All rights reserved. This program and the accompanying materials
|
|
||||||
* are made available under the terms of the Common Public License v0.5
|
|
||||||
* which accompanies this distribution, and is available at
|
|
||||||
* http://www.eclipse.org/legal/cpl-v05.html
|
|
||||||
*
|
|
||||||
* Contributors:
|
|
||||||
* IBM Corp. - Rational Software - initial implementation
|
|
||||||
******************************************************************************/
|
|
||||||
/*
|
|
||||||
* Created on Jun 13, 2003
|
|
||||||
*/
|
|
||||||
package org.eclipse.cdt.internal.core.search;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author aniefer
|
|
||||||
*
|
|
||||||
* To change the template for this generated type comment go to
|
|
||||||
* Window>Preferences>Java>Code Generation>Code and Comments
|
|
||||||
*/
|
|
||||||
public class Util {
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public Util() {
|
|
||||||
super();
|
|
||||||
// TODO Auto-generated constructor stub
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static String bind(String string) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -52,15 +52,15 @@ public abstract class CSearchPattern
|
||||||
case ICSearchConstants.TYPE:
|
case ICSearchConstants.TYPE:
|
||||||
pattern = createTypePattern( patternString, limitTo, matchMode, caseSensitive );
|
pattern = createTypePattern( patternString, limitTo, matchMode, caseSensitive );
|
||||||
break;
|
break;
|
||||||
case ICSearchConstants.METHOD:
|
//case ICSearchConstants.METHOD:
|
||||||
pattern = createMethodPattern( patternString, limitTo, matchMode, caseSensitive );
|
// pattern = createMethodPattern( patternString, limitTo, matchMode, caseSensitive );
|
||||||
break;
|
// break;
|
||||||
case ICSearchConstants.CONSTRUCTOR:
|
case ICSearchConstants.CONSTRUCTOR:
|
||||||
pattern = createConstructorPattern( patternString, limitTo, matchMode, caseSensitive );
|
pattern = createConstructorPattern( patternString, limitTo, matchMode, caseSensitive );
|
||||||
break;
|
break;
|
||||||
case ICSearchConstants.FIELD:
|
//case ICSearchConstants.FIELD:
|
||||||
pattern = createFieldPattern( patternString, limitTo, matchMode, caseSensitive );
|
// pattern = createFieldPattern( patternString, limitTo, matchMode, caseSensitive );
|
||||||
break;
|
// break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return pattern;
|
return pattern;
|
||||||
|
|
|
@ -9,19 +9,17 @@
|
||||||
* IBM Corp. - Rational Software - initial implementation
|
* IBM Corp. - Rational Software - initial implementation
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
/*
|
/*
|
||||||
* Created on Jun 13, 2003
|
* Created on May 30, 2003
|
||||||
*/
|
*/
|
||||||
package org.eclipse.cdt.internal.core.search.processing;
|
package org.eclipse.cdt.internal.core.search.processing;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author bgheorgh
|
||||||
|
*/
|
||||||
import org.eclipse.core.runtime.IProgressMonitor;
|
import org.eclipse.core.runtime.IProgressMonitor;
|
||||||
|
|
||||||
/**
|
|
||||||
* @author aniefer
|
|
||||||
*
|
|
||||||
* To change the template for this generated type comment go to
|
|
||||||
* Window>Preferences>Java>Code Generation>Code and Comments
|
|
||||||
*/
|
|
||||||
public interface IJob {
|
public interface IJob {
|
||||||
|
|
||||||
/* Waiting policies */
|
/* Waiting policies */
|
||||||
int ForceImmediate = 1;
|
int ForceImmediate = 1;
|
||||||
int CancelIfNotReady = 2;
|
int CancelIfNotReady = 2;
|
||||||
|
@ -32,7 +30,7 @@ public interface IJob {
|
||||||
boolean COMPLETE = true;
|
boolean COMPLETE = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Answer true if the job belongs to a given family (tag)
|
* True if job belongs to the passed in jobFamily
|
||||||
*/
|
*/
|
||||||
public boolean belongsTo(String jobFamily);
|
public boolean belongsTo(String jobFamily);
|
||||||
/**
|
/**
|
||||||
|
@ -48,4 +46,5 @@ public interface IJob {
|
||||||
* Answer whether the job is ready to run.
|
* Answer whether the job is ready to run.
|
||||||
*/
|
*/
|
||||||
public boolean isReadyToRun();
|
public boolean isReadyToRun();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,32 +9,426 @@
|
||||||
* IBM Corp. - Rational Software - initial implementation
|
* IBM Corp. - Rational Software - initial implementation
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
/*
|
/*
|
||||||
* Created on Jun 13, 2003
|
* Created on May 30, 2003
|
||||||
*/
|
*/
|
||||||
package org.eclipse.cdt.internal.core.search.processing;
|
package org.eclipse.cdt.internal.core.search.processing;
|
||||||
|
|
||||||
/**
|
import org.eclipse.core.runtime.IProgressMonitor;
|
||||||
* @author aniefer
|
import org.eclipse.core.runtime.OperationCanceledException;
|
||||||
*
|
import org.eclipse.core.runtime.SubProgressMonitor;
|
||||||
* To change the template for this generated type comment go to
|
import org.eclipse.cdt.internal.core.search.Util;
|
||||||
* Window>Preferences>Java>Code Generation>Code and Comments
|
|
||||||
*/
|
|
||||||
public class JobManager implements Runnable {
|
|
||||||
|
|
||||||
/**
|
public abstract class JobManager implements Runnable {
|
||||||
*
|
|
||||||
*/
|
/* queue of jobs to execute */
|
||||||
public JobManager() {
|
protected IJob[] awaitingJobs = new IJob[10];
|
||||||
super();
|
protected int jobStart = 0;
|
||||||
// TODO Auto-generated constructor stub
|
protected int jobEnd = -1;
|
||||||
|
protected boolean executing = false;
|
||||||
|
|
||||||
|
/* background processing */
|
||||||
|
protected Thread thread;
|
||||||
|
|
||||||
|
/* flag indicating whether job execution is enabled or not */
|
||||||
|
private boolean enabled = true;
|
||||||
|
|
||||||
|
public static boolean VERBOSE = false;
|
||||||
|
/* flag indicating that the activation has completed */
|
||||||
|
public boolean activated = false;
|
||||||
|
|
||||||
|
private int awaitingClients = 0;
|
||||||
|
|
||||||
|
public static void verbose(String log) {
|
||||||
|
System.out.println("(" + Thread.currentThread() + ") " + log); //$NON-NLS-1$//$NON-NLS-2$
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/**
|
||||||
* @see java.lang.Runnable#run()
|
* Invoked exactly once, in background, before starting processing any job
|
||||||
|
*/
|
||||||
|
public void activateProcessing() {
|
||||||
|
this.activated = true;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Answer the amount of awaiting jobs.
|
||||||
|
*/
|
||||||
|
public synchronized int awaitingJobsCount() {
|
||||||
|
|
||||||
|
// pretend busy in case concurrent job attempts performing before activated
|
||||||
|
if (!activated)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return jobEnd - jobStart + 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Answers the first job in the queue, or null if there is no job available
|
||||||
|
* Until the job has completed, the job manager will keep answering the same job.
|
||||||
|
*/
|
||||||
|
public synchronized IJob currentJob() {
|
||||||
|
|
||||||
|
if (!enabled)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (jobStart <= jobEnd) {
|
||||||
|
return awaitingJobs[jobStart];
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void disable() {
|
||||||
|
enabled = false;
|
||||||
|
if (VERBOSE)
|
||||||
|
JobManager.verbose("DISABLING background indexing"); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Remove the index from cache for a given project.
|
||||||
|
* Passing null as a job family discards them all.
|
||||||
|
*/
|
||||||
|
public void discardJobs(String jobFamily) {
|
||||||
|
|
||||||
|
if (VERBOSE)
|
||||||
|
JobManager.verbose("DISCARD background job family - " + jobFamily); //$NON-NLS-1$
|
||||||
|
|
||||||
|
boolean wasEnabled = isEnabled();
|
||||||
|
try {
|
||||||
|
IJob currentJob;
|
||||||
|
// cancel current job if it belongs to the given family
|
||||||
|
synchronized(this){
|
||||||
|
currentJob = this.currentJob();
|
||||||
|
disable();
|
||||||
|
}
|
||||||
|
if (currentJob != null
|
||||||
|
&& (jobFamily == null || currentJob.belongsTo(jobFamily))) {
|
||||||
|
|
||||||
|
currentJob.cancel();
|
||||||
|
|
||||||
|
// wait until current active job has finished
|
||||||
|
while (thread != null && executing){
|
||||||
|
try {
|
||||||
|
if (VERBOSE)
|
||||||
|
JobManager.verbose("-> waiting end of current background job - " + currentJob); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
Thread.sleep(50);
|
||||||
|
} catch(InterruptedException e){
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// flush and compact awaiting jobs
|
||||||
|
int loc = -1;
|
||||||
|
synchronized(this) {
|
||||||
|
for (int i = jobStart; i <= jobEnd; i++) {
|
||||||
|
currentJob = awaitingJobs[i];
|
||||||
|
awaitingJobs[i] = null;
|
||||||
|
if (!(jobFamily == null
|
||||||
|
|| currentJob.belongsTo(jobFamily))) { // copy down, compacting
|
||||||
|
awaitingJobs[++loc] = currentJob;
|
||||||
|
} else {
|
||||||
|
if (VERBOSE)
|
||||||
|
JobManager.verbose("-> discarding background job - " + currentJob); //$NON-NLS-1$
|
||||||
|
currentJob.cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
jobStart = 0;
|
||||||
|
jobEnd = loc;
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (wasEnabled)
|
||||||
|
enable();
|
||||||
|
}
|
||||||
|
if (VERBOSE)
|
||||||
|
JobManager.verbose("DISCARD DONE with background job family - " + jobFamily); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void enable() {
|
||||||
|
enabled = true;
|
||||||
|
if (VERBOSE)
|
||||||
|
JobManager.verbose("ENABLING background indexing"); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized boolean isEnabled() {
|
||||||
|
return enabled;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Advance to the next available job, once the current one has been completed.
|
||||||
|
* Note: clients awaiting until the job count is zero are still waiting at this point.
|
||||||
|
*/
|
||||||
|
protected synchronized void moveToNextJob() {
|
||||||
|
|
||||||
|
//if (!enabled) return;
|
||||||
|
|
||||||
|
if (jobStart <= jobEnd) {
|
||||||
|
awaitingJobs[jobStart++] = null;
|
||||||
|
if (jobStart > jobEnd) {
|
||||||
|
jobStart = 0;
|
||||||
|
jobEnd = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* When idle, give chance to do something
|
||||||
|
*/
|
||||||
|
protected void notifyIdle(long idlingTime) {
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* This API is allowing to run one job in concurrence with background processing.
|
||||||
|
* Indeed since other jobs are performed in background, resource sharing might be
|
||||||
|
* an issue.Therefore, this functionality allows a given job to be run without
|
||||||
|
* colliding with background ones.
|
||||||
|
* Note: multiple thread might attempt to perform concurrent jobs at the same time,
|
||||||
|
* and should synchronize (it is deliberately left to clients to decide whether
|
||||||
|
* concurrent jobs might interfere or not. In general, multiple read jobs are ok).
|
||||||
|
*
|
||||||
|
* Waiting policy can be:
|
||||||
|
* IJobConstants.ForceImmediateSearch
|
||||||
|
* IJobConstants.CancelIfNotReadyToSearch
|
||||||
|
* IJobConstants.WaitUntilReadyToSearch
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public boolean performConcurrentJob(
|
||||||
|
IJob searchJob,
|
||||||
|
int waitingPolicy,
|
||||||
|
IProgressMonitor progress) {
|
||||||
|
|
||||||
|
if (VERBOSE)
|
||||||
|
JobManager.verbose("STARTING concurrent job - " + searchJob); //$NON-NLS-1$
|
||||||
|
if (!searchJob.isReadyToRun()) {
|
||||||
|
if (VERBOSE)
|
||||||
|
JobManager.verbose("ABORTED concurrent job - " + searchJob); //$NON-NLS-1$
|
||||||
|
return IJob.FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
int concurrentJobWork = 100;
|
||||||
|
if (progress != null)
|
||||||
|
progress.beginTask("", concurrentJobWork); //$NON-NLS-1$
|
||||||
|
boolean status = IJob.FAILED;
|
||||||
|
if (awaitingJobsCount() > 0) {
|
||||||
|
switch (waitingPolicy) {
|
||||||
|
|
||||||
|
case IJob.ForceImmediate :
|
||||||
|
if (VERBOSE)
|
||||||
|
JobManager.verbose("-> NOT READY - forcing immediate - " + searchJob);//$NON-NLS-1$
|
||||||
|
boolean wasEnabled = isEnabled();
|
||||||
|
try {
|
||||||
|
disable(); // pause indexing
|
||||||
|
status = searchJob.execute(progress == null ? null : new SubProgressMonitor(progress, concurrentJobWork));
|
||||||
|
} finally {
|
||||||
|
if (wasEnabled)
|
||||||
|
enable();
|
||||||
|
}
|
||||||
|
if (VERBOSE)
|
||||||
|
JobManager.verbose("FINISHED concurrent job - " + searchJob); //$NON-NLS-1$
|
||||||
|
return status;
|
||||||
|
|
||||||
|
case IJob.CancelIfNotReady :
|
||||||
|
if (VERBOSE)
|
||||||
|
JobManager.verbose("-> NOT READY - cancelling - " + searchJob); //$NON-NLS-1$
|
||||||
|
if (progress != null) progress.setCanceled(true);
|
||||||
|
if (VERBOSE)
|
||||||
|
JobManager.verbose("CANCELED concurrent job - " + searchJob); //$NON-NLS-1$
|
||||||
|
throw new OperationCanceledException();
|
||||||
|
|
||||||
|
case IJob.WaitUntilReady :
|
||||||
|
int awaitingWork;
|
||||||
|
IJob previousJob = null;
|
||||||
|
IJob currentJob;
|
||||||
|
IProgressMonitor subProgress = null;
|
||||||
|
int totalWork = this.awaitingJobsCount();
|
||||||
|
if (progress != null && totalWork > 0) {
|
||||||
|
subProgress = new SubProgressMonitor(progress, concurrentJobWork / 2);
|
||||||
|
subProgress.beginTask("", totalWork); //$NON-NLS-1$
|
||||||
|
concurrentJobWork = concurrentJobWork / 2;
|
||||||
|
}
|
||||||
|
int originalPriority = this.thread.getPriority();
|
||||||
|
try {
|
||||||
|
synchronized(this) {
|
||||||
|
|
||||||
|
// use local variable to avoid potential NPE (see Bug 20435 NPE when searching java method)
|
||||||
|
Thread t = this.thread;
|
||||||
|
if (t != null) {
|
||||||
|
t.setPriority(Thread.currentThread().getPriority());
|
||||||
|
}
|
||||||
|
this.awaitingClients++;
|
||||||
|
}
|
||||||
|
while ((awaitingWork = awaitingJobsCount()) > 0) {
|
||||||
|
if (subProgress != null && subProgress.isCanceled())
|
||||||
|
throw new OperationCanceledException();
|
||||||
|
currentJob = currentJob();
|
||||||
|
// currentJob can be null when jobs have been added to the queue but job manager is not enabled
|
||||||
|
if (currentJob != null && currentJob != previousJob) {
|
||||||
|
if (VERBOSE)
|
||||||
|
JobManager.verbose("-> NOT READY - waiting until ready - " + searchJob);//$NON-NLS-1$
|
||||||
|
if (subProgress != null) {
|
||||||
|
subProgress.subTask(
|
||||||
|
Util.bind("manager.filesToIndex", Integer.toString(awaitingWork))); //$NON-NLS-1$
|
||||||
|
subProgress.worked(1);
|
||||||
|
}
|
||||||
|
previousJob = currentJob;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
Thread.sleep(50);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
synchronized(this) {
|
||||||
|
this.awaitingClients--;
|
||||||
|
|
||||||
|
// use local variable to avoid potential NPE (see Bug 20435 NPE when searching java method)
|
||||||
|
Thread t = this.thread;
|
||||||
|
if (t != null) {
|
||||||
|
t.setPriority(originalPriority);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (subProgress != null) {
|
||||||
|
subProgress.done();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
status = searchJob.execute(progress == null ? null : new SubProgressMonitor(progress, concurrentJobWork));
|
||||||
|
if (progress != null) {
|
||||||
|
progress.done();
|
||||||
|
}
|
||||||
|
if (VERBOSE)
|
||||||
|
JobManager.verbose("FINISHED concurrent job - " + searchJob); //$NON-NLS-1$
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract String processName();
|
||||||
|
|
||||||
|
public synchronized void request(IJob job) {
|
||||||
|
if (!job.isReadyToRun()) {
|
||||||
|
if (VERBOSE)
|
||||||
|
JobManager.verbose("ABORTED request of background job - " + job); //$NON-NLS-1$
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// append the job to the list of ones to process later on
|
||||||
|
int size = awaitingJobs.length;
|
||||||
|
if (++jobEnd == size) { // when growing, relocate jobs starting at position 0
|
||||||
|
jobEnd -= jobStart;
|
||||||
|
System.arraycopy(
|
||||||
|
awaitingJobs,
|
||||||
|
jobStart,
|
||||||
|
(awaitingJobs = new IJob[size * 2]),
|
||||||
|
0,
|
||||||
|
jobEnd);
|
||||||
|
jobStart = 0;
|
||||||
|
}
|
||||||
|
awaitingJobs[jobEnd] = job;
|
||||||
|
if (VERBOSE)
|
||||||
|
JobManager.verbose("REQUEST background job - " + job); //$NON-NLS-1$
|
||||||
|
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Flush current state
|
||||||
|
*/
|
||||||
|
public void reset() {
|
||||||
|
if (VERBOSE)
|
||||||
|
JobManager.verbose("Reset"); //$NON-NLS-1$
|
||||||
|
|
||||||
|
if (thread != null) {
|
||||||
|
discardJobs(null); // discard all jobs
|
||||||
|
} else {
|
||||||
|
/* initiate background processing */
|
||||||
|
thread = new Thread(this, this.processName());
|
||||||
|
thread.setDaemon(true);
|
||||||
|
// less prioritary by default, priority is raised if clients are actively waiting on it
|
||||||
|
thread.setPriority(Thread.NORM_PRIORITY-1);
|
||||||
|
thread.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Infinite loop performing resource indexing
|
||||||
*/
|
*/
|
||||||
public void run() {
|
public void run() {
|
||||||
// TODO Auto-generated method stub
|
|
||||||
|
|
||||||
|
long idlingStart = -1;
|
||||||
|
activateProcessing();
|
||||||
|
try {
|
||||||
|
while (this.thread != null) {
|
||||||
|
try {
|
||||||
|
IJob job;
|
||||||
|
if ((job = currentJob()) == null) {
|
||||||
|
if (idlingStart < 0)
|
||||||
|
idlingStart = System.currentTimeMillis();
|
||||||
|
notifyIdle(System.currentTimeMillis() - idlingStart);
|
||||||
|
Thread.sleep(500);
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
idlingStart = -1;
|
||||||
|
}
|
||||||
|
if (VERBOSE) {
|
||||||
|
JobManager.verbose(awaitingJobsCount() + " awaiting jobs"); //$NON-NLS-1$
|
||||||
|
JobManager.verbose("STARTING background job - " + job); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
executing = true;
|
||||||
|
/*boolean status = */job.execute(null);
|
||||||
|
//if (status == FAILED) request(job);
|
||||||
|
} finally {
|
||||||
|
executing = false;
|
||||||
|
if (VERBOSE) {
|
||||||
|
JobManager.verbose("FINISHED background job - " + job); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
moveToNextJob();
|
||||||
|
if (this.awaitingClients == 0) {
|
||||||
|
Thread.sleep(50);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (InterruptedException e) { // background indexing was interrupted
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
if (this.thread != null) { // if not shutting down
|
||||||
|
// log exception
|
||||||
|
org.eclipse.cdt.internal.core.model.Util.log(e, "Background Indexer Crash Recovery"); //$NON-NLS-1$
|
||||||
|
|
||||||
|
// keep job manager alive
|
||||||
|
this.discardJobs(null);
|
||||||
|
this.thread = null;
|
||||||
|
this.reset(); // this will fork a new thread with no waiting jobs, some indexes will be inconsistent
|
||||||
|
}
|
||||||
|
throw e;
|
||||||
|
} catch (Error e) {
|
||||||
|
if (this.thread != null && !(e instanceof ThreadDeath)) {
|
||||||
|
// log exception
|
||||||
|
org.eclipse.cdt.internal.core.model.Util.log(e, "Background Indexer Crash Recovery"); //$NON-NLS-1$
|
||||||
|
|
||||||
|
// keep job manager alive
|
||||||
|
this.discardJobs(null);
|
||||||
|
this.thread = null;
|
||||||
|
this.reset(); // this will fork a new thread with no waiting jobs, some indexes will be inconsistent
|
||||||
|
}
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Stop background processing, and wait until the current job is completed before returning
|
||||||
|
*/
|
||||||
|
public void shutdown() {
|
||||||
|
|
||||||
|
disable();
|
||||||
|
discardJobs(null); // will wait until current executing job has completed
|
||||||
|
Thread thread = this.thread;
|
||||||
|
this.thread = null; // mark the job manager as shutting down so that the thread will stop by itself
|
||||||
|
try {
|
||||||
|
if (thread != null) { // see http://bugs.eclipse.org/bugs/show_bug.cgi?id=31858
|
||||||
|
thread.join();
|
||||||
|
}
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
StringBuffer buffer = new StringBuffer(10);
|
||||||
|
buffer.append("Enabled:").append(this.enabled).append('\n'); //$NON-NLS-1$
|
||||||
|
int numJobs = jobEnd - jobStart + 1;
|
||||||
|
buffer.append("Jobs in queue:").append(numJobs).append('\n'); //$NON-NLS-1$
|
||||||
|
for (int i = 0; i < numJobs && i < 15; i++) {
|
||||||
|
buffer.append(i).append(" - job["+i+"]: ").append(awaitingJobs[jobStart+i]).append('\n'); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
}
|
||||||
|
return buffer.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -140,6 +140,9 @@ public class CCorePlugin extends Plugin {
|
||||||
fIndexModel = IndexModel.getDefault();
|
fIndexModel = IndexModel.getDefault();
|
||||||
fIndexModel.startup();
|
fIndexModel.startup();
|
||||||
|
|
||||||
|
//Fired up the new indexer
|
||||||
|
fCoreModel.startIndexing();
|
||||||
|
|
||||||
fDescriptorManager = new CDescriptorManager();
|
fDescriptorManager = new CDescriptorManager();
|
||||||
fDescriptorManager.startup();
|
fDescriptorManager.startup();
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,14 @@
|
||||||
Began structuring expressions and declarators in Parser for ISourceElementRequestor.
|
Began structuring expressions and declarators in Parser for ISourceElementRequestor.
|
||||||
Updated other packages to use new interfaces.
|
Updated other packages to use new interfaces.
|
||||||
|
|
||||||
|
2003-06-25 Bogdan Gheorghe
|
||||||
|
Added a new checkbox to the Indexer tab of the C/C++ Project Settings
|
||||||
|
to allow the new indexer to be turned on or off.
|
||||||
|
* src/org/eclipse/cdt/ui/wizards/IndexerBlock.java
|
||||||
|
|
||||||
|
Modified the CSearchPage to work with the new CSearchConstants
|
||||||
|
* src/org/eclipse/cdt/internal/ui/search/CSearchPage.java
|
||||||
|
|
||||||
2003-06-24 Thomas Fletcher
|
2003-06-24 Thomas Fletcher
|
||||||
|
|
||||||
- Proposals will now include additional help information with them
|
- Proposals will now include additional help information with them
|
||||||
|
|
|
@ -161,8 +161,8 @@ public class CSearchPage extends DialogPage implements ISearchPage, ICSearchCons
|
||||||
};
|
};
|
||||||
|
|
||||||
fSearchFor[ TYPE ].addSelectionListener(cElementInitializer);
|
fSearchFor[ TYPE ].addSelectionListener(cElementInitializer);
|
||||||
fSearchFor[ METHOD ].addSelectionListener(cElementInitializer);
|
fSearchFor[ FUNCTION ].addSelectionListener(cElementInitializer);
|
||||||
fSearchFor[ FIELD ].addSelectionListener(cElementInitializer);
|
fSearchFor[ MEMBER ].addSelectionListener(cElementInitializer);
|
||||||
fSearchFor[CONSTRUCTOR].addSelectionListener(cElementInitializer);
|
fSearchFor[CONSTRUCTOR].addSelectionListener(cElementInitializer);
|
||||||
//fSearchFor[ PACKAGE ].addSelectionListener(cElementInitializer);
|
//fSearchFor[ PACKAGE ].addSelectionListener(cElementInitializer);
|
||||||
|
|
||||||
|
@ -283,34 +283,34 @@ public class CSearchPage extends DialogPage implements ISearchPage, ICSearchCons
|
||||||
}
|
}
|
||||||
private void setLimitTo(int searchFor) {
|
private void setLimitTo(int searchFor) {
|
||||||
fLimitTo[ DECLARATIONS ].setEnabled( true );
|
fLimitTo[ DECLARATIONS ].setEnabled( true );
|
||||||
fLimitTo[ IMPLEMENTORS ].setEnabled( false);
|
//fLimitTo[ IMPLEMENTORS ].setEnabled( false);
|
||||||
fLimitTo[ REFERENCES ].setEnabled( true );
|
fLimitTo[ REFERENCES ].setEnabled( true );
|
||||||
fLimitTo[ ALL_OCCURRENCES ].setEnabled( true );
|
fLimitTo[ ALL_OCCURRENCES ].setEnabled( true );
|
||||||
fLimitTo[ READ_ACCESSES ].setEnabled( false);
|
//fLimitTo[ READ_ACCESSES ].setEnabled( false);
|
||||||
fLimitTo[ WRITE_ACCESSES ].setEnabled( false);
|
//fLimitTo[ WRITE_ACCESSES ].setEnabled( false);
|
||||||
|
|
||||||
if (!(searchFor == TYPE || searchFor == INTERFACE) && fLimitTo[IMPLEMENTORS].getSelection()) {
|
// if (!(searchFor == TYPE || searchFor == INTERFACE) && fLimitTo[IMPLEMENTORS].getSelection()) {
|
||||||
fLimitTo[ IMPLEMENTORS ].setSelection(false);
|
// fLimitTo[ IMPLEMENTORS ].setSelection(false);
|
||||||
fLimitTo[ REFERENCES ].setSelection(true);
|
// fLimitTo[ REFERENCES ].setSelection(true);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
if (!(searchFor == FIELD) && (getLimitTo() == READ_ACCESSES || getLimitTo() == WRITE_ACCESSES)) {
|
// if (!(searchFor == FIELD) && (getLimitTo() == READ_ACCESSES || getLimitTo() == WRITE_ACCESSES)) {
|
||||||
fLimitTo[ getLimitTo()].setSelection(false);
|
// fLimitTo[ getLimitTo()].setSelection(false);
|
||||||
fLimitTo[ REFERENCES ].setSelection(true);
|
// fLimitTo[ REFERENCES ].setSelection(true);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
switch (searchFor) {
|
// switch (searchFor) {
|
||||||
case TYPE:
|
// case TYPE:
|
||||||
case INTERFACE:
|
// case INTERFACE:
|
||||||
fLimitTo[ IMPLEMENTORS ].setEnabled(true);
|
// fLimitTo[ IMPLEMENTORS ].setEnabled(true);
|
||||||
break;
|
// break;
|
||||||
case FIELD:
|
// case FIELD:
|
||||||
fLimitTo[ READ_ACCESSES ].setEnabled(true);
|
// fLimitTo[ READ_ACCESSES ].setEnabled(true);
|
||||||
fLimitTo[ WRITE_ACCESSES ].setEnabled(true);
|
// fLimitTo[ WRITE_ACCESSES ].setEnabled(true);
|
||||||
break;
|
// break;
|
||||||
default :
|
// default :
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
private Control createSearchFor(Composite parent) {
|
private Control createSearchFor(Composite parent) {
|
||||||
|
|
|
@ -7,6 +7,7 @@ package org.eclipse.cdt.ui.wizards;
|
||||||
|
|
||||||
import org.eclipse.cdt.core.CCorePlugin;
|
import org.eclipse.cdt.core.CCorePlugin;
|
||||||
import org.eclipse.cdt.core.index.IndexModel;
|
import org.eclipse.cdt.core.index.IndexModel;
|
||||||
|
import org.eclipse.cdt.internal.core.search.indexing.IndexManager;
|
||||||
import org.eclipse.cdt.utils.ui.swt.IValidation;
|
import org.eclipse.cdt.utils.ui.swt.IValidation;
|
||||||
import org.eclipse.core.resources.IProject;
|
import org.eclipse.core.resources.IProject;
|
||||||
import org.eclipse.core.runtime.IProgressMonitor;
|
import org.eclipse.core.runtime.IProgressMonitor;
|
||||||
|
@ -18,6 +19,7 @@ import org.eclipse.swt.widgets.Composite;
|
||||||
|
|
||||||
public class IndexerBlock implements IWizardTab {
|
public class IndexerBlock implements IWizardTab {
|
||||||
private Button indexerSwitch;
|
private Button indexerSwitch;
|
||||||
|
private Button indexerSwitch2;
|
||||||
IProject project;
|
IProject project;
|
||||||
IValidation page;
|
IValidation page;
|
||||||
|
|
||||||
|
@ -39,8 +41,13 @@ public class IndexerBlock implements IWizardTab {
|
||||||
|
|
||||||
indexerSwitch = new Button(composite, SWT.CHECK | SWT.RIGHT);
|
indexerSwitch = new Button(composite, SWT.CHECK | SWT.RIGHT);
|
||||||
indexerSwitch.setAlignment(SWT.LEFT);
|
indexerSwitch.setAlignment(SWT.LEFT);
|
||||||
indexerSwitch.setText("Enable indexing service for this project");
|
indexerSwitch.setText("Enable CTAGS indexing service for this project");
|
||||||
indexerSwitch.setSelection(indexer.isEnabled(project));
|
indexerSwitch.setSelection(indexer.isEnabled(project));
|
||||||
|
|
||||||
|
indexerSwitch2 = new Button(composite, SWT.CHECK | SWT.RIGHT);
|
||||||
|
indexerSwitch2.setAlignment(SWT.LEFT);
|
||||||
|
indexerSwitch2.setText("Enable NEW indexing service for this project");
|
||||||
|
indexerSwitch2.setSelection(false);
|
||||||
return composite;
|
return composite;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,6 +57,9 @@ public class IndexerBlock implements IWizardTab {
|
||||||
public void doRun(IProject project, IProgressMonitor monitor) {
|
public void doRun(IProject project, IProgressMonitor monitor) {
|
||||||
IndexModel indexer = CCorePlugin.getDefault().getIndexModel();
|
IndexModel indexer = CCorePlugin.getDefault().getIndexModel();
|
||||||
indexer.setEnabled(project, indexerSwitch.getSelection());
|
indexer.setEnabled(project, indexerSwitch.getSelection());
|
||||||
|
|
||||||
|
IndexManager newIndexer = CCorePlugin.getDefault().getCoreModel().getIndexManager();
|
||||||
|
newIndexer.setEnabled(project, indexerSwitch2.getSelection());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -79,12 +89,21 @@ public class IndexerBlock implements IWizardTab {
|
||||||
*/
|
*/
|
||||||
public void setVisible(boolean visible) {
|
public void setVisible(boolean visible) {
|
||||||
IndexModel indexer = CCorePlugin.getDefault().getIndexModel();
|
IndexModel indexer = CCorePlugin.getDefault().getIndexModel();
|
||||||
|
IndexManager newIndexer = CCorePlugin.getDefault().getCoreModel().getIndexManager();
|
||||||
|
|
||||||
if (indexerSwitch != null) {
|
if (indexerSwitch != null) {
|
||||||
//indexerSwitch.setAlignment(SWT.LEFT);
|
//indexerSwitch.setAlignment(SWT.LEFT);
|
||||||
//indexerSwitch.setText("Enable indexing service for this project");
|
//indexerSwitch.setText("Enable indexing service for this project");
|
||||||
indexerSwitch.setSelection(indexer.isEnabled(project));
|
indexerSwitch.setSelection(indexer.isEnabled(project));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (indexerSwitch2 != null) {
|
||||||
|
//indexerSwitch.setAlignment(SWT.LEFT);
|
||||||
|
//indexerSwitch.setText("Enable indexing service for this project");
|
||||||
|
indexerSwitch2.setSelection(newIndexer.isEnabled(project));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue