1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
|
/*
SPDX-FileCopyrightText: 2006 David Nolden <david.nolden.kdevelop@art-master.de>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef LEXERCACHE_H
#define LEXERCACHE_H
#include <hashedstring.h>
#include "macro.h"
#include <qdatetime.h>
#include <qfileinfo.h>
#include "cachemanager.h"
//#define LEXERCACHE_DEBUG
class LexerCache;
class CachedLexedFile : public QSharedData, public CacheNode
{
public:
///@todo add and manage the set of included files
CachedLexedFile(const HashedString& fileName, LexerCache* manager);
inline void addString(const HashedString& string)
{
if (!m_definedMacroNames[ string ]) {
m_strings.insert(string);
}
}
void addDefinedMacro(const Macro& macro);
void addUsedMacro(const Macro& macro);
void addIncludeFile(const HashedString& file, const QDateTime& modificationTime);
inline bool hasString(const HashedString& string) const
{
return m_strings[string];
}
QDateTime modificationTime() const;
void addProblem(const Problem& p);
QList<Problem> problems() const;
//The parameter should be a CachedLexedFile that was lexed AFTER the content of this file
void merge(const CachedLexedFile& file);
bool operator < (const CachedLexedFile& rhs) const
{
return m_fileName < rhs.m_fileName;
}
size_t hash() const;
HashedString fileName() const
{
return m_fileName;
}
const HashedStringSet& includeFiles() const
{
return m_includeFiles;
}
const MacroSet& definedMacros() const
{
return m_definedMacros;
}
const MacroSet& usedMacros() const
{
return m_usedMacros;
}
///Should contain a modification-time for each include-file
const QMap<HashedString, QDateTime>& allModificationTimes() const
{
return m_allModificationTimes;
}
private:
friend class LexerCache;
HashedString m_fileName;
QDateTime m_modificationTime;
HashedStringSet m_strings; //Set of all strings that can be affected by macros from outside
HashedStringSet m_includeFiles; //Set of all files
MacroSet m_usedMacros; //Set of all macros that were used, and were defined outside of this file
MacroSet m_definedMacros; //Set of all macros that were defined while lexing this file
HashedStringSet m_definedMacroNames;
QList<Problem> m_problems;
QMap<HashedString, QDateTime> m_allModificationTimes;
/*
Needed data:
1. Set of all strings that appear in this file(For memory-reasons they should be taken from a global string-repository, because many will be the same)
2. Set of all macros that were defined outside of, but affected the file
Algorithm:
Iterate over all available macros, and check whether they affect the file. If it does, make sure that the macro is in the macro-set and has the same body.
If the check fails: We need to reparse.
*/
};
typedef QExplicitlySharedDataPointer<CachedLexedFile> CachedLexedFilePointer;
struct CachedLexedFilePointerCompare {
bool operator() (const CachedLexedFilePointer& lhs, const CachedLexedFilePointer& rhs) const
{
return (*lhs) < (*rhs);
}
};
class Driver;
class LexerCache : public CacheManager
{
public:
explicit LexerCache(Driver* d);
virtual ~LexerCache() {}
void addLexedFile(const CachedLexedFilePointer& file);
///Returns zero if no fitting file is available for the current context
CachedLexedFilePointer lexedFile(const HashedString& fileName);
void clear();
const HashedString& unifyString(const HashedString& str)
{
QSet<HashedString>::const_iterator it = m_totalStringSet.find(str);
if (it != m_totalStringSet.end()) {
return *it;
} else {
m_totalStringSet.insert(str);
return str;
}
}
virtual void saveMemory();
private:
///before this can be called, initFileModificationCache should be called once
QDateTime fileModificationTimeCached(const HashedString& fileName);
void initFileModificationCache();
virtual void erase(const CacheNode* node);
bool sourceChanged(const CachedLexedFile& file);///Returns true if the file itself, or any of its dependencies was modified.
//typedef __gnu_cxx::hash_multimap<HashedString, CachedLexedFilePointer> CachedLexedFileMap;
typedef std::multimap<HashedString, CachedLexedFilePointer> CachedLexedFileMap;
CachedLexedFileMap m_files;
QSet<HashedString> m_totalStringSet; ///This is used to reduce memory-usage: Most strings appear again and again. Because QString is reference-counted, this set contains a unique copy of each string to use for each appearance of the string
struct FileModificationCache {
QDateTime m_readTime;
QDateTime m_modificationTime;
};
typedef QHash<HashedString, FileModificationCache> FileModificationMap;
FileModificationMap m_fileModificationCache;
Driver* m_driver;
QDateTime m_currentDateTime;
};
#endif
|