1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-08-09 01:05:38 +02:00

Bug 317435: Change to file-encoding shall trigger index update.

This commit is contained in:
Markus Schorn 2010-06-24 13:01:39 +00:00
parent 5a013d6320
commit 1285350432
12 changed files with 144 additions and 39 deletions

View file

@ -2278,4 +2278,42 @@ public class IndexBugsTests extends BaseTestCase {
index.releaseReadLock(); index.releaseReadLock();
} }
} }
public void testUpdateForContentTypeChange_283080() throws Exception {
IIndexBinding[] r;
final IProject prj = fCProject.getProject();
IFile file= TestSourceReader.createFile(prj, "a.cpp", "// \u0110 \n int a;");
file.setCharset("US-ASCII", new NullProgressMonitor());
waitForIndexer(fCProject);
final IIndex index= CCorePlugin.getIndexManager().getIndex(fCProject);
int offset1= 0;
index.acquireReadLock();
try {
r = index.findBindings("a".toCharArray(), IndexFilter.ALL_DECLARED, null);
assertEquals(1, r.length);
IIndexName[] defs = index.findDefinitions(r[0]);
assertEquals(1, defs.length);
offset1= defs[0].getNodeOffset();
} finally {
index.releaseReadLock();
}
file.setCharset("UTF-8", new NullProgressMonitor());
waitForIndexer(fCProject);
int offset2= 0;
index.acquireReadLock();
try {
r = index.findBindings("a".toCharArray(), IndexFilter.ALL_DECLARED, null);
assertEquals(1, r.length);
IIndexName[] defs = index.findDefinitions(r[0]);
assertEquals(1, defs.length);
offset1= defs[0].getNodeOffset();
} finally {
index.releaseReadLock();
}
assertTrue(offset1 != offset2);
}
} }

View file

@ -76,6 +76,14 @@ public interface IIndexFile {
*/ */
int getScannerConfigurationHashcode() throws CoreException; int getScannerConfigurationHashcode() throws CoreException;
/**
* Returns the hash-code of the file encoding that was used to parse the file.
* <code>0</code> will be returned in case the hash-code is unknown.
* @return the hash-code of the file encoding or <code>0</code>.
* @since 5.3
*/
int getEncodingHashcode() throws CoreException;
/** /**
* Find all names within the given range. * Find all names within the given range.
*/ */

View file

@ -83,11 +83,16 @@ public abstract class FileContent {
return InternalParserUtil.createWorkspaceFileContent(file); return InternalParserUtil.createWorkspaceFileContent(file);
} }
public static FileContent createForExternalFileLocation(String fileLocation) {
return createForExternalFileLocation(fileLocation, InternalParserUtil.SYSTEM_DEFAULT_ENCODING);
}
/** /**
* Creates a file content object for a file location that is not part of the workspace * Creates a file content object for a file location that is not part of the workspace
* @since 5.3
*/ */
public static FileContent createForExternalFileLocation(String fileLocation) { public static FileContent createForExternalFileLocation(String fileLocation, String encoding) {
return InternalParserUtil.createExternalFileContent(fileLocation); return InternalParserUtil.createExternalFileContent(fileLocation, encoding);
} }
/** /**

View file

@ -40,6 +40,12 @@ public interface IIndexFragmentFile extends IIndexFile {
*/ */
void setScannerConfigurationHashcode(int hashcode) throws CoreException; void setScannerConfigurationHashcode(int hashcode) throws CoreException;
/**
* Sets the hash-code of the file encoding.
* @param hashcode a hash-code or <code>0</code> if it is unknown.
*/
void setEncodingHashcode(int hashcode) throws CoreException;
/** /**
* Returns whether this file contains content in its * Returns whether this file contains content in its
* associated fragment. Files without content are inserted to track includes. * associated fragment. Files without content are inserted to track includes.

View file

@ -17,10 +17,10 @@ import java.util.HashMap;
import org.eclipse.cdt.core.index.IIndexFileLocation; import org.eclipse.cdt.core.index.IIndexFileLocation;
import org.eclipse.cdt.core.model.AbstractLanguage; import org.eclipse.cdt.core.model.AbstractLanguage;
import org.eclipse.cdt.core.model.ILanguage; import org.eclipse.cdt.core.model.ILanguage;
import org.eclipse.cdt.core.parser.CodeReader;
import org.eclipse.cdt.core.parser.FileContent; import org.eclipse.cdt.core.parser.FileContent;
import org.eclipse.cdt.core.parser.IScannerInfo; import org.eclipse.cdt.core.parser.IScannerInfo;
import org.eclipse.cdt.internal.core.index.IndexFileLocation; import org.eclipse.cdt.internal.core.index.IndexFileLocation;
import org.eclipse.cdt.internal.core.parser.InternalParserUtil;
import org.eclipse.cdt.internal.core.pdom.IndexerInputAdapter; import org.eclipse.cdt.internal.core.pdom.IndexerInputAdapter;
import org.eclipse.cdt.internal.core.pdom.indexer.FileExistsCache; import org.eclipse.cdt.internal.core.pdom.indexer.FileExistsCache;
import org.eclipse.core.filesystem.URIUtil; import org.eclipse.core.filesystem.URIUtil;
@ -51,6 +51,16 @@ public class StandaloneIndexerInputAdapter extends IndexerInputAdapter {
return new File(URIUtil.toPath(location.getURI()).toOSString()).lastModified(); return new File(URIUtil.toPath(location.getURI()).toOSString()).lastModified();
} }
@Override
public String getEncoding(IIndexFileLocation ifl) {
String encoding= getFileEncoding(getASTPath(ifl));
if (encoding == null)
return InternalParserUtil.SYSTEM_DEFAULT_ENCODING;
return encoding;
}
@Override @Override
public boolean isSourceUnit(Object tu) { public boolean isSourceUnit(Object tu) {
return isValidSourceUnitName((String) tu); return isValidSourceUnitName((String) tu);
@ -130,24 +140,23 @@ public class StandaloneIndexerInputAdapter extends IndexerInputAdapter {
@Override @Override
public FileContent getCodeReader(Object tu) { public FileContent getCodeReader(Object tu) {
try {
String stu = (String) tu; String stu = (String) tu;
String fileEncoding = getFileEncoding(stu);
return FileContent.createForExternalFileLocation(stu, fileEncoding);
}
public String getFileEncoding(String stu) {
String fileEncoding = null; String fileEncoding = null;
// query file's encoding, if we find it and use it to create CodeReader // query file's encoding, if we find it and use it to create CodeReader
FileEncodingRegistry fileEncodingRegistry = fIndexer.getFileEncodingRegistry(); FileEncodingRegistry fileEncodingRegistry = fIndexer.getFileEncodingRegistry();
if(fileEncodingRegistry != null){ if(fileEncodingRegistry != null){
fileEncoding = fileEncodingRegistry.getFileEncoding(stu); fileEncoding = fileEncodingRegistry.getFileEncoding(stu);
} }
if (fileEncoding == null)
return InternalParserUtil.SYSTEM_DEFAULT_ENCODING;
if (fileEncoding != null) { return fileEncoding;
// TODO this is bad
return FileContent.adapt(new CodeReader(stu, fileEncoding));
} else {
return FileContent.createForExternalFileLocation((String) tu);
}
} catch (IOException e) {
}
return null;
} }
@Override @Override

View file

@ -36,7 +36,7 @@ import org.eclipse.core.runtime.Path;
* Utility for creating code readers * Utility for creating code readers
*/ */
public class InternalParserUtil extends ParserFactory { public class InternalParserUtil extends ParserFactory {
private static final String SYSTEM_DEFAULT_ENCODING = System.getProperty("file.encoding"); //$NON-NLS-1$ public static final String SYSTEM_DEFAULT_ENCODING = System.getProperty("file.encoding"); //$NON-NLS-1$
/** /**
* Normalizes the path by using the location of the file, if possible. * Normalizes the path by using the location of the file, if possible.
@ -133,7 +133,7 @@ public class InternalParserUtil extends ParserFactory {
if (res instanceof IFile) if (res instanceof IFile)
return createWorkspaceFileContent((IFile) res); return createWorkspaceFileContent((IFile) res);
} }
return createExternalFileContent(ifl.getURI().getPath()); return createExternalFileContent(ifl.getURI().getPath(), SYSTEM_DEFAULT_ENCODING);
} }
public static InternalFileContent createWorkspaceFileContent(IFile file) { public static InternalFileContent createWorkspaceFileContent(IFile file) {
@ -170,7 +170,7 @@ public class InternalParserUtil extends ParserFactory {
* Creates a code reader for an external location, normalizing path to * Creates a code reader for an external location, normalizing path to
* canonical path. * canonical path.
*/ */
public static InternalFileContent createExternalFileContent(String externalLocation) { public static InternalFileContent createExternalFileContent(String externalLocation, String encoding) {
File includeFile = new File(externalLocation); File includeFile = new File(externalLocation);
if (includeFile.isFile()) { if (includeFile.isFile()) {
// Use the canonical path so that in case of non-case-sensitive OSs // Use the canonical path so that in case of non-case-sensitive OSs
@ -185,7 +185,7 @@ public class InternalParserUtil extends ParserFactory {
return null; return null;
} }
try { try {
return createFileContent(path, SYSTEM_DEFAULT_ENCODING, in); return createFileContent(path, encoding, in);
} finally { } finally {
try { try {
in.close(); in.close();

View file

@ -445,13 +445,16 @@ public abstract class AbstractIndexerTask extends PDOMWriter {
private boolean isModified(boolean checkTimestamps, boolean checkFileContentsHash, IIndexFileLocation ifl, private boolean isModified(boolean checkTimestamps, boolean checkFileContentsHash, IIndexFileLocation ifl,
Object tu, IIndexFragmentFile file) throws CoreException { Object tu, IIndexFragmentFile file) throws CoreException {
boolean timestampDifferent = checkTimestamps && fResolver.getLastModified(ifl) != file.getTimestamp(); if (checkTimestamps) {
if (timestampDifferent) { if (fResolver.getLastModified(ifl) != file.getTimestamp() ||
fResolver.getEncoding(ifl).hashCode() != file.getEncodingHashcode()) {
if (checkFileContentsHash && computeFileContentsHash(tu) == file.getContentsHash()) { if (checkFileContentsHash && computeFileContentsHash(tu) == file.getContentsHash()) {
return false; return false;
} }
return true;
} }
return timestampDifferent; }
return false;
} }
private void requestUpdate(int linkageID, IIndexFileLocation ifl, IIndexFragmentFile ifile) { private void requestUpdate(int linkageID, IIndexFileLocation ifl, IIndexFragmentFile ifile) {

View file

@ -70,4 +70,8 @@ public abstract class IndexerInputAdapter extends ASTFilePathResolver {
*/ */
public abstract FileContent getCodeReader(Object tu); public abstract FileContent getCodeReader(Object tu);
/**
* Returns the encoding for the file.
*/
public abstract String getEncoding(IIndexFileLocation ifl);
} }

View file

@ -193,11 +193,14 @@ public class PDOM extends PlatformObject implements IPDOM {
* 95.0 - parameter packs, bug 294730. * 95.0 - parameter packs, bug 294730.
* 96.0 - storing pack expansions in the template parameter map, bug 294730. * 96.0 - storing pack expansions in the template parameter map, bug 294730.
* 97.0 - storing file contents hash in PDOMFile, bug 302083. * 97.0 - storing file contents hash in PDOMFile, bug 302083.
* 98.0 - strongly typed enums, bug 305975. * #98.0# - strongly typed enums, bug 305975. <<CDT 7.0.0>>
*
* CDT 8.0 development (versions not supported on the 7.0.x branch)
* 110.0 - update index on encoding change, bug 317435.
*/ */
private static final int MIN_SUPPORTED_VERSION= version(98, 0); private static final int MIN_SUPPORTED_VERSION= version(110, 0);
private static final int MAX_SUPPORTED_VERSION= version(98, Short.MAX_VALUE); private static final int MAX_SUPPORTED_VERSION= version(110, Short.MAX_VALUE);
private static final int DEFAULT_VERSION = version(98, 0); private static final int DEFAULT_VERSION = version(110, 0);
private static int version(int major, int minor) { private static int version(int major, int minor) {
return (major << 16) + minor; return (major << 16) + minor;

View file

@ -38,6 +38,7 @@ import org.eclipse.cdt.core.dom.ast.ICompositeType;
import org.eclipse.cdt.core.dom.ast.IEnumeration; import org.eclipse.cdt.core.dom.ast.IEnumeration;
import org.eclipse.cdt.core.dom.ast.IProblemBinding; import org.eclipse.cdt.core.dom.ast.IProblemBinding;
import org.eclipse.cdt.core.dom.ast.ITypedef; import org.eclipse.cdt.core.dom.ast.ITypedef;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDirective; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDirective;
@ -45,7 +46,6 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplate;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace; import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespaceAlias; import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespaceAlias;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier;
import org.eclipse.cdt.core.index.IIndexFileLocation; import org.eclipse.cdt.core.index.IIndexFileLocation;
import org.eclipse.cdt.core.index.IIndexInclude; import org.eclipse.cdt.core.index.IIndexInclude;
import org.eclipse.cdt.core.parser.IProblem; import org.eclipse.cdt.core.parser.IProblem;
@ -461,7 +461,6 @@ abstract public class PDOMWriter {
YieldableIndexLock lock) throws CoreException, InterruptedException { YieldableIndexLock lock) throws CoreException, InterruptedException {
Set<IIndexFileLocation> clearedContexts= Collections.emptySet(); Set<IIndexFileLocation> clearedContexts= Collections.emptySet();
IIndexFragmentFile file; IIndexFragmentFile file;
long timestamp = fResolver.getLastModified(location);
// We create a temporary PDOMFile with zero timestamp, add names to it, then replace contents // We create a temporary PDOMFile with zero timestamp, add names to it, then replace contents
// of the old file from the temporary one, then delete the temporary file. The write lock on // of the old file from the temporary one, then delete the temporary file. The write lock on
// the index can be yielded between adding names to the temporary file, if another thread // the index can be yielded between adding names to the temporary file, if another thread
@ -503,7 +502,8 @@ abstract public class PDOMWriter {
} }
index.setFileContent(file, linkageID, includeInfos, macros, names, fResolver, lock); index.setFileContent(file, linkageID, includeInfos, macros, names, fResolver, lock);
} }
file.setTimestamp(timestamp); file.setTimestamp(fResolver.getLastModified(location));
file.setEncodingHashcode(fResolver.getEncoding(location).hashCode());
file.setContentsHash(fileContentsHash); file.setContentsHash(fileContentsHash);
file = index.commitUncommittedFile(); file = index.commitUncommittedFile();
} finally { } finally {

View file

@ -40,9 +40,9 @@ import org.eclipse.cdt.core.index.IIndexName;
import org.eclipse.cdt.internal.core.index.IIndexFragment; import org.eclipse.cdt.internal.core.index.IIndexFragment;
import org.eclipse.cdt.internal.core.index.IIndexFragmentFile; import org.eclipse.cdt.internal.core.index.IIndexFragmentFile;
import org.eclipse.cdt.internal.core.index.IIndexFragmentName; import org.eclipse.cdt.internal.core.index.IIndexFragmentName;
import org.eclipse.cdt.internal.core.index.IWritableIndex.IncludeInformation;
import org.eclipse.cdt.internal.core.index.IWritableIndexFragment; import org.eclipse.cdt.internal.core.index.IWritableIndexFragment;
import org.eclipse.cdt.internal.core.index.IndexFileLocation; import org.eclipse.cdt.internal.core.index.IndexFileLocation;
import org.eclipse.cdt.internal.core.index.IWritableIndex.IncludeInformation;
import org.eclipse.cdt.internal.core.pdom.PDOM; import org.eclipse.cdt.internal.core.pdom.PDOM;
import org.eclipse.cdt.internal.core.pdom.YieldableIndexLock; import org.eclipse.cdt.internal.core.pdom.YieldableIndexLock;
import org.eclipse.cdt.internal.core.pdom.db.BTree; import org.eclipse.cdt.internal.core.pdom.db.BTree;
@ -73,10 +73,11 @@ public class PDOMFile implements IIndexFragmentFile {
private static final int TIME_STAMP = 24; private static final int TIME_STAMP = 24;
private static final int CONTENT_HASH= 32; private static final int CONTENT_HASH= 32;
private static final int SCANNER_CONFIG_HASH= 40; private static final int SCANNER_CONFIG_HASH= 40;
private static final int LAST_USING_DIRECTIVE= 44; private static final int ENCODING_HASH= 44;
private static final int FIRST_MACRO_REFERENCE= 48; private static final int LAST_USING_DIRECTIVE= 48;
private static final int FIRST_MACRO_REFERENCE= 52;
private static final int RECORD_SIZE= 52; private static final int RECORD_SIZE= 56;
public static class Comparator implements IBTreeComparator { public static class Comparator implements IBTreeComparator {
private Database db; private Database db;
@ -224,6 +225,7 @@ public class PDOMFile implements IIndexFragmentFile {
} }
setTimestamp(sourceFile.getTimestamp()); setTimestamp(sourceFile.getTimestamp());
setEncodingHashcode(sourceFile.getEncodingHashcode());
setContentsHash(sourceFile.getContentsHash()); setContentsHash(sourceFile.getContentsHash());
setScannerConfigurationHashcode(sourceFile.getScannerConfigurationHashcode()); setScannerConfigurationHashcode(sourceFile.getScannerConfigurationHashcode());
@ -293,6 +295,16 @@ public class PDOMFile implements IIndexFragmentFile {
db.putInt(record + SCANNER_CONFIG_HASH, hashcode); db.putInt(record + SCANNER_CONFIG_HASH, hashcode);
} }
public int getEncodingHashcode() throws CoreException {
Database db = fLinkage.getDB();
return db.getInt(record + ENCODING_HASH);
}
public void setEncodingHashcode(int hashcode) throws CoreException {
Database db= fLinkage.getDB();
db.putInt(record + ENCODING_HASH, hashcode);
}
private PDOMName getFirstName() throws CoreException { private PDOMName getFirstName() throws CoreException {
long namerec = fLinkage.getDB().getRecPtr(record + FIRST_NAME); long namerec = fLinkage.getDB().getRecPtr(record + FIRST_NAME);
return namerec != 0 ? new PDOMName(fLinkage, namerec) : null; return namerec != 0 ? new PDOMName(fLinkage, namerec) : null;

View file

@ -28,8 +28,10 @@ import org.eclipse.cdt.core.model.LanguageManager;
import org.eclipse.cdt.core.parser.FileContent; import org.eclipse.cdt.core.parser.FileContent;
import org.eclipse.cdt.core.parser.IScannerInfo; import org.eclipse.cdt.core.parser.IScannerInfo;
import org.eclipse.cdt.core.parser.ScannerInfo; import org.eclipse.cdt.core.parser.ScannerInfo;
import org.eclipse.cdt.internal.core.parser.InternalParserUtil;
import org.eclipse.cdt.internal.core.pdom.IndexerInputAdapter; import org.eclipse.cdt.internal.core.pdom.IndexerInputAdapter;
import org.eclipse.cdt.internal.core.resources.PathCanonicalizationStrategy; import org.eclipse.cdt.internal.core.resources.PathCanonicalizationStrategy;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.CoreException;
@ -172,6 +174,21 @@ public class ProjectIndexerInputAdapter extends IndexerInputAdapter {
return 0; return 0;
} }
@Override
public String getEncoding(IIndexFileLocation ifl) {
String fullPath= ifl.getFullPath();
if (fullPath != null) {
IResource res= ResourcesPlugin.getWorkspace().getRoot().findMember(new Path(fullPath));
if (res instanceof IFile) {
try {
return ((IFile) res).getCharset();
} catch (CoreException e) {
}
}
}
return InternalParserUtil.SYSTEM_DEFAULT_ENCODING;
}
@Override @Override
public AbstractLanguage[] getLanguages(Object tuo, boolean bothForHeaders) { public AbstractLanguage[] getLanguages(Object tuo, boolean bothForHeaders) {
if (tuo instanceof PotentialTranslationUnit) { if (tuo instanceof PotentialTranslationUnit) {