From 1285350432c8611ab48aced4bd96ef02001c9732 Mon Sep 17 00:00:00 2001 From: Markus Schorn Date: Thu, 24 Jun 2010 13:01:39 +0000 Subject: [PATCH] Bug 317435: Change to file-encoding shall trigger index update. --- .../internal/index/tests/IndexBugsTests.java | 38 ++++++++++++++++ .../eclipse/cdt/core/index/IIndexFile.java | 8 ++++ .../eclipse/cdt/core/parser/FileContent.java | 9 +++- .../core/index/IIndexFragmentFile.java | 6 +++ .../StandaloneIndexerInputAdapter.java | 43 +++++++++++-------- .../core/parser/InternalParserUtil.java | 8 ++-- .../core/pdom/AbstractIndexerTask.java | 13 +++--- .../core/pdom/IndexerInputAdapter.java | 4 ++ .../eclipse/cdt/internal/core/pdom/PDOM.java | 11 +++-- .../cdt/internal/core/pdom/PDOMWriter.java | 6 +-- .../cdt/internal/core/pdom/dom/PDOMFile.java | 20 +++++++-- .../indexer/ProjectIndexerInputAdapter.java | 17 ++++++++ 12 files changed, 144 insertions(+), 39 deletions(-) diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBugsTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBugsTests.java index 0d17bbe0c43..e9331d9361f 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBugsTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBugsTests.java @@ -2278,4 +2278,42 @@ public class IndexBugsTests extends BaseTestCase { 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); + } } \ No newline at end of file diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndexFile.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndexFile.java index 353a20dc6a8..cb6f18fc722 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndexFile.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndexFile.java @@ -76,6 +76,14 @@ public interface IIndexFile { */ int getScannerConfigurationHashcode() throws CoreException; + /** + * Returns the hash-code of the file encoding that was used to parse the file. + * 0 will be returned in case the hash-code is unknown. + * @return the hash-code of the file encoding or 0. + * @since 5.3 + */ + int getEncodingHashcode() throws CoreException; + /** * Find all names within the given range. */ diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/FileContent.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/FileContent.java index bc9a4d20953..d386f644ea7 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/FileContent.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/FileContent.java @@ -83,11 +83,16 @@ public abstract class FileContent { 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 + * @since 5.3 */ - public static FileContent createForExternalFileLocation(String fileLocation) { - return InternalParserUtil.createExternalFileContent(fileLocation); + public static FileContent createForExternalFileLocation(String fileLocation, String encoding) { + return InternalParserUtil.createExternalFileContent(fileLocation, encoding); } /** diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IIndexFragmentFile.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IIndexFragmentFile.java index 2a74bfc873a..887133feb52 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IIndexFragmentFile.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IIndexFragmentFile.java @@ -40,6 +40,12 @@ public interface IIndexFragmentFile extends IIndexFile { */ void setScannerConfigurationHashcode(int hashcode) throws CoreException; + /** + * Sets the hash-code of the file encoding. + * @param hashcode a hash-code or 0 if it is unknown. + */ + void setEncodingHashcode(int hashcode) throws CoreException; + /** * Returns whether this file contains content in its * associated fragment. Files without content are inserted to track includes. diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/indexer/StandaloneIndexerInputAdapter.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/indexer/StandaloneIndexerInputAdapter.java index fc9726992c9..a2d3c69ec45 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/indexer/StandaloneIndexerInputAdapter.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/indexer/StandaloneIndexerInputAdapter.java @@ -17,10 +17,10 @@ import java.util.HashMap; import org.eclipse.cdt.core.index.IIndexFileLocation; import org.eclipse.cdt.core.model.AbstractLanguage; 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.IScannerInfo; 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.indexer.FileExistsCache; import org.eclipse.core.filesystem.URIUtil; @@ -51,6 +51,16 @@ public class StandaloneIndexerInputAdapter extends IndexerInputAdapter { 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 public boolean isSourceUnit(Object tu) { return isValidSourceUnitName((String) tu); @@ -130,24 +140,23 @@ public class StandaloneIndexerInputAdapter extends IndexerInputAdapter { @Override public FileContent getCodeReader(Object tu) { - try { - String stu = (String) tu; - String fileEncoding = null; - // query file's encoding, if we find it and use it to create CodeReader - FileEncodingRegistry fileEncodingRegistry = fIndexer.getFileEncodingRegistry(); - if(fileEncodingRegistry != null){ - fileEncoding = fileEncodingRegistry.getFileEncoding(stu); - } + String stu = (String) tu; + String fileEncoding = getFileEncoding(stu); - if (fileEncoding != null) { - // TODO this is bad - return FileContent.adapt(new CodeReader(stu, fileEncoding)); - } else { - return FileContent.createForExternalFileLocation((String) tu); - } - } catch (IOException e) { + return FileContent.createForExternalFileLocation(stu, fileEncoding); + } + + public String getFileEncoding(String stu) { + String fileEncoding = null; + // query file's encoding, if we find it and use it to create CodeReader + FileEncodingRegistry fileEncodingRegistry = fIndexer.getFileEncodingRegistry(); + if(fileEncodingRegistry != null){ + fileEncoding = fileEncodingRegistry.getFileEncoding(stu); } - return null; + if (fileEncoding == null) + return InternalParserUtil.SYSTEM_DEFAULT_ENCODING; + + return fileEncoding; } @Override diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/InternalParserUtil.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/InternalParserUtil.java index 6073ffccee8..23ef5a39786 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/InternalParserUtil.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/InternalParserUtil.java @@ -36,7 +36,7 @@ import org.eclipse.core.runtime.Path; * Utility for creating code readers */ 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. @@ -133,7 +133,7 @@ public class InternalParserUtil extends ParserFactory { if (res instanceof IFile) return createWorkspaceFileContent((IFile) res); } - return createExternalFileContent(ifl.getURI().getPath()); + return createExternalFileContent(ifl.getURI().getPath(), SYSTEM_DEFAULT_ENCODING); } 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 * canonical path. */ - public static InternalFileContent createExternalFileContent(String externalLocation) { + public static InternalFileContent createExternalFileContent(String externalLocation, String encoding) { File includeFile = new File(externalLocation); if (includeFile.isFile()) { // Use the canonical path so that in case of non-case-sensitive OSs @@ -185,7 +185,7 @@ public class InternalParserUtil extends ParserFactory { return null; } try { - return createFileContent(path, SYSTEM_DEFAULT_ENCODING, in); + return createFileContent(path, encoding, in); } finally { try { in.close(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/AbstractIndexerTask.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/AbstractIndexerTask.java index 99ea7204c1d..44caaddfd82 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/AbstractIndexerTask.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/AbstractIndexerTask.java @@ -445,13 +445,16 @@ public abstract class AbstractIndexerTask extends PDOMWriter { private boolean isModified(boolean checkTimestamps, boolean checkFileContentsHash, IIndexFileLocation ifl, Object tu, IIndexFragmentFile file) throws CoreException { - boolean timestampDifferent = checkTimestamps && fResolver.getLastModified(ifl) != file.getTimestamp(); - if (timestampDifferent) { - if (checkFileContentsHash && computeFileContentsHash(tu) == file.getContentsHash()) { - return false; + if (checkTimestamps) { + if (fResolver.getLastModified(ifl) != file.getTimestamp() || + fResolver.getEncoding(ifl).hashCode() != file.getEncodingHashcode()) { + if (checkFileContentsHash && computeFileContentsHash(tu) == file.getContentsHash()) { + return false; + } + return true; } } - return timestampDifferent; + return false; } private void requestUpdate(int linkageID, IIndexFileLocation ifl, IIndexFragmentFile ifile) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/IndexerInputAdapter.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/IndexerInputAdapter.java index 62f6ccd28e7..e83b16a52db 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/IndexerInputAdapter.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/IndexerInputAdapter.java @@ -70,4 +70,8 @@ public abstract class IndexerInputAdapter extends ASTFilePathResolver { */ public abstract FileContent getCodeReader(Object tu); + /** + * Returns the encoding for the file. + */ + public abstract String getEncoding(IIndexFileLocation ifl); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java index 88036473e75..59c3bd1c169 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java @@ -193,11 +193,14 @@ public class PDOM extends PlatformObject implements IPDOM { * 95.0 - parameter packs, bug 294730. * 96.0 - storing pack expansions in the template parameter map, bug 294730. * 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 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 MAX_SUPPORTED_VERSION= version(98, Short.MAX_VALUE); - private static final int DEFAULT_VERSION = version(98, 0); + private static final int MIN_SUPPORTED_VERSION= version(110, 0); + private static final int MAX_SUPPORTED_VERSION= version(110, Short.MAX_VALUE); + private static final int DEFAULT_VERSION = version(110, 0); private static int version(int major, int minor) { return (major << 16) + minor; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMWriter.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMWriter.java index b51b6bbb483..fa6382de502 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMWriter.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMWriter.java @@ -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.IProblemBinding; 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.ICPPASTTemplateId; 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.ICPPNamespaceAlias; 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.IIndexInclude; import org.eclipse.cdt.core.parser.IProblem; @@ -461,7 +461,6 @@ abstract public class PDOMWriter { YieldableIndexLock lock) throws CoreException, InterruptedException { Set clearedContexts= Collections.emptySet(); IIndexFragmentFile file; - long timestamp = fResolver.getLastModified(location); // 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 // 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); } - file.setTimestamp(timestamp); + file.setTimestamp(fResolver.getLastModified(location)); + file.setEncodingHashcode(fResolver.getEncoding(location).hashCode()); file.setContentsHash(fileContentsHash); file = index.commitUncommittedFile(); } finally { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMFile.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMFile.java index b79e64f1f5b..bdd985b3cf6 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMFile.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMFile.java @@ -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.IIndexFragmentFile; 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.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.YieldableIndexLock; 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 CONTENT_HASH= 32; private static final int SCANNER_CONFIG_HASH= 40; - private static final int LAST_USING_DIRECTIVE= 44; - private static final int FIRST_MACRO_REFERENCE= 48; + private static final int ENCODING_HASH= 44; + 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 { private Database db; @@ -224,6 +225,7 @@ public class PDOMFile implements IIndexFragmentFile { } setTimestamp(sourceFile.getTimestamp()); + setEncodingHashcode(sourceFile.getEncodingHashcode()); setContentsHash(sourceFile.getContentsHash()); setScannerConfigurationHashcode(sourceFile.getScannerConfigurationHashcode()); @@ -293,6 +295,16 @@ public class PDOMFile implements IIndexFragmentFile { 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 { long namerec = fLinkage.getDB().getRecPtr(record + FIRST_NAME); return namerec != 0 ? new PDOMName(fLinkage, namerec) : null; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/ProjectIndexerInputAdapter.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/ProjectIndexerInputAdapter.java index 94d4f16165e..142bb47444e 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/ProjectIndexerInputAdapter.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/ProjectIndexerInputAdapter.java @@ -28,8 +28,10 @@ import org.eclipse.cdt.core.model.LanguageManager; import org.eclipse.cdt.core.parser.FileContent; import org.eclipse.cdt.core.parser.IScannerInfo; 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.resources.PathCanonicalizationStrategy; +import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; @@ -172,6 +174,21 @@ public class ProjectIndexerInputAdapter extends IndexerInputAdapter { 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 public AbstractLanguage[] getLanguages(Object tuo, boolean bothForHeaders) { if (tuo instanceof PotentialTranslationUnit) {