forked from qt-creator/qt-creator
MimeDatabase: Remove bestMatch, which was broken beyond repair
The problem is that, if you check e.g. a .pro file against all C/C++ mime types, and these define magic matchers, it would find that .pro doesn't match C/C++ mime types by extension, so it would open the file to find a magic match. Even though the extension .pro would identify it already as a qmake .pro file when checking for the mime type globally. Change-Id: I3341187e88e2263bf38169c3c99e5d2161e2a9ee Reviewed-by: Daniel Teske <daniel.teske@theqtcompany.com> Reviewed-by: Orgad Shaneh <orgads@gmail.com>
This commit is contained in:
@@ -352,79 +352,6 @@ QStringList MimeDatabase::allGlobPatterns()
|
|||||||
return patterns;
|
return patterns;
|
||||||
}
|
}
|
||||||
|
|
||||||
static MimeType mimeForName(const QList<MimeType> &types, const QString &name)
|
|
||||||
{
|
|
||||||
foreach (const MimeType &mt, types)
|
|
||||||
if (mt.matchesName(name))
|
|
||||||
return mt;
|
|
||||||
return MimeType();
|
|
||||||
}
|
|
||||||
|
|
||||||
MimeType MimeDatabase::bestMatch(const QString &fileName, const QList<MimeType> &types)
|
|
||||||
{
|
|
||||||
// Copied together from mimeTypeForFile(QFileInfo) code path ...
|
|
||||||
// It would be better to be able to work on a list of mime types directly
|
|
||||||
|
|
||||||
// Check for directory. We just ignore the code path for special unix nodes.
|
|
||||||
if (fileName.endsWith(QLatin1Char('/')))
|
|
||||||
return mimeForName(types, QLatin1String("inode/directory"));
|
|
||||||
|
|
||||||
auto d = MimeDatabasePrivate::instance();
|
|
||||||
QMutexLocker locker(&d->mutex);
|
|
||||||
|
|
||||||
QStringList candidatesByName = d->provider()->bestMatchByFileName(QFileInfo(fileName).fileName(),
|
|
||||||
types);
|
|
||||||
if (candidatesByName.count() == 1) {
|
|
||||||
MimeType mt = mimeForName(types, candidatesByName.first());
|
|
||||||
if (mt.isValid())
|
|
||||||
return mt;
|
|
||||||
candidatesByName.clear();
|
|
||||||
}
|
|
||||||
// Extension is unknown, or matches multiple mimetypes.
|
|
||||||
// Pass 2) Match on content, if we can read the data
|
|
||||||
QFile file(QFileInfo(fileName).absoluteFilePath());
|
|
||||||
file.open(QIODevice::ReadOnly);
|
|
||||||
if (file.isOpen()) {
|
|
||||||
// Read 16K in one go (QIODEVICE_BUFFERSIZE in qiodevice_p.h).
|
|
||||||
// This is much faster than seeking back and forth into QIODevice.
|
|
||||||
const QByteArray data = file.peek(16384);
|
|
||||||
|
|
||||||
int magicAccuracy = 0;
|
|
||||||
MimeType candidateByData;
|
|
||||||
if (data.isEmpty()) {
|
|
||||||
magicAccuracy = 100;
|
|
||||||
candidateByData = mimeForName(types, QLatin1String("application/x-zerosize"));
|
|
||||||
} else {
|
|
||||||
candidateByData = d->provider()->bestMatchByMagic(data, types, &magicAccuracy);
|
|
||||||
if (!candidateByData.isValid()) {
|
|
||||||
if (isTextFile(data)) {
|
|
||||||
magicAccuracy = 5;
|
|
||||||
candidateByData = mimeForName(types, QLatin1String("text/plain"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Disambiguate conflicting extensions (if magic matching found something)
|
|
||||||
if (candidateByData.isValid() && magicAccuracy > 0) {
|
|
||||||
// "for glob_match in glob_matches:"
|
|
||||||
// "if glob_match is subclass or equal to sniffed_type, use glob_match"
|
|
||||||
const QString sniffedMime = candidateByData.name();
|
|
||||||
foreach (const QString &m, candidatesByName) {
|
|
||||||
if (d->inherits(m, sniffedMime)) {
|
|
||||||
// We have magic + pattern pointing to this, so it's a pretty good match
|
|
||||||
return mimeForName(types, m);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return candidateByData;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (candidatesByName.count() > 1) {
|
|
||||||
candidatesByName.sort();
|
|
||||||
return mimeForName(types, candidatesByName.first());
|
|
||||||
}
|
|
||||||
return MimeType();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\fn MimeType MimeDatabase::mimeTypeForName(const QString &nameOrAlias) const;
|
\fn MimeType MimeDatabase::mimeTypeForName(const QString &nameOrAlias) const;
|
||||||
Returns a MIME type for \a nameOrAlias or an invalid one if none found.
|
Returns a MIME type for \a nameOrAlias or an invalid one if none found.
|
||||||
|
@@ -87,7 +87,6 @@ public:
|
|||||||
static void addMimeTypes(const QString &fileName);
|
static void addMimeTypes(const QString &fileName);
|
||||||
static QString allFiltersString(QString *allFilesFilter = 0);
|
static QString allFiltersString(QString *allFilesFilter = 0);
|
||||||
static QStringList allGlobPatterns();
|
static QStringList allGlobPatterns();
|
||||||
static MimeType bestMatch(const QString &fileName, const QList<MimeType> &types);
|
|
||||||
static QMap<int, QList<Internal::MimeMagicRule> > magicRulesForMimeType(const MimeType &mimeType); // priority -> rules
|
static QMap<int, QList<Internal::MimeMagicRule> > magicRulesForMimeType(const MimeType &mimeType); // priority -> rules
|
||||||
static void setGlobPatternsForMimeType(const MimeType &mimeType, const QStringList &patterns);
|
static void setGlobPatternsForMimeType(const MimeType &mimeType, const QStringList &patterns);
|
||||||
static void setMagicRulesForMimeType(const MimeType &mimeType,
|
static void setMagicRulesForMimeType(const MimeType &mimeType,
|
||||||
|
@@ -719,38 +719,6 @@ QStringList MimeXMLProvider::findByFileName(const QString &fileName, QString *fo
|
|||||||
return matchingMimeTypes;
|
return matchingMimeTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList MimeXMLProvider::bestMatchByFileName(const QString &fileName, const QList<MimeType> &types)
|
|
||||||
{
|
|
||||||
ensureLoaded();
|
|
||||||
|
|
||||||
// this is slow :(
|
|
||||||
// this would be much better if MimeType had references to their globs & magics
|
|
||||||
MimeAllGlobPatterns globs;
|
|
||||||
// fast patterns are fast (hash lookup), no need to reduce that set
|
|
||||||
globs.m_fastPatterns = m_mimeTypeGlobs.m_fastPatterns;
|
|
||||||
// fill highWeight and lowWeight glob lists
|
|
||||||
QSet<QString> names;
|
|
||||||
foreach (const MimeType &mt, types)
|
|
||||||
names.insert(mt.name());
|
|
||||||
foreach (const MimeGlobPattern &pattern, m_mimeTypeGlobs.m_highWeightGlobs) {
|
|
||||||
if (names.contains(pattern.mimeType()))
|
|
||||||
globs.m_highWeightGlobs.append(pattern);
|
|
||||||
}
|
|
||||||
foreach (const MimeGlobPattern &pattern, m_mimeTypeGlobs.m_lowWeightGlobs) {
|
|
||||||
if (names.contains(pattern.mimeType()))
|
|
||||||
globs.m_lowWeightGlobs.append(pattern);
|
|
||||||
}
|
|
||||||
QString foundSuffix;
|
|
||||||
const QStringList matchingMimeTypes = globs.matchingGlobs(fileName, &foundSuffix);
|
|
||||||
// result can still contain types that are not in our list, because of the fast patterns
|
|
||||||
QStringList result;
|
|
||||||
foreach (const QString &match, matchingMimeTypes) {
|
|
||||||
if (names.contains(match))
|
|
||||||
result.append(match);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
MimeType MimeXMLProvider::findByMagic(const QByteArray &data, int *accuracyPtr)
|
MimeType MimeXMLProvider::findByMagic(const QByteArray &data, int *accuracyPtr)
|
||||||
{
|
{
|
||||||
ensureLoaded();
|
ensureLoaded();
|
||||||
@@ -769,30 +737,6 @@ MimeType MimeXMLProvider::findByMagic(const QByteArray &data, int *accuracyPtr)
|
|||||||
return mimeTypeForName(candidate);
|
return mimeTypeForName(candidate);
|
||||||
}
|
}
|
||||||
|
|
||||||
MimeType MimeXMLProvider::bestMatchByMagic(const QByteArray &data, const QList<MimeType> &types, int *accuracyPtr)
|
|
||||||
{
|
|
||||||
ensureLoaded();
|
|
||||||
|
|
||||||
QSet<QString> names;
|
|
||||||
foreach (const MimeType &mt, types)
|
|
||||||
names.insert(mt.name());
|
|
||||||
|
|
||||||
QString candidate;
|
|
||||||
|
|
||||||
foreach (const MimeMagicRuleMatcher &matcher, m_magicMatchers) {
|
|
||||||
if (!names.contains(matcher.mimetype()))
|
|
||||||
continue;
|
|
||||||
if (matcher.matches(data)) {
|
|
||||||
const int priority = matcher.priority();
|
|
||||||
if (priority > *accuracyPtr) {
|
|
||||||
*accuracyPtr = priority;
|
|
||||||
candidate = matcher.mimetype();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return mimeTypeForName(candidate);
|
|
||||||
}
|
|
||||||
|
|
||||||
QMap<int, QList<MimeMagicRule> > MimeXMLProvider::magicRulesForMimeType(const MimeType &mimeType)
|
QMap<int, QList<MimeMagicRule> > MimeXMLProvider::magicRulesForMimeType(const MimeType &mimeType)
|
||||||
{
|
{
|
||||||
QMap<int, QList<MimeMagicRule> > result;
|
QMap<int, QList<MimeMagicRule> > result;
|
||||||
|
@@ -75,8 +75,6 @@ public:
|
|||||||
virtual void loadGenericIcon(MimeTypePrivate &) {}
|
virtual void loadGenericIcon(MimeTypePrivate &) {}
|
||||||
|
|
||||||
// Qt Creator additions
|
// Qt Creator additions
|
||||||
virtual QStringList bestMatchByFileName(const QString &fileName, const QList<MimeType> &types) = 0;
|
|
||||||
virtual MimeType bestMatchByMagic(const QByteArray &data, const QList<MimeType> &types, int *accuracyPtr) = 0;
|
|
||||||
virtual QMap<int, QList<MimeMagicRule> > magicRulesForMimeType(const MimeType &mimeType) = 0;
|
virtual QMap<int, QList<MimeMagicRule> > magicRulesForMimeType(const MimeType &mimeType) = 0;
|
||||||
virtual void setGlobPatternsForMimeType(const MimeType &mimeType, const QStringList &patterns) = 0;
|
virtual void setGlobPatternsForMimeType(const MimeType &mimeType, const QStringList &patterns) = 0;
|
||||||
virtual void setMagicRulesForMimeType(const MimeType &mimeType, const QMap<int, QList<MimeMagicRule> > &rules) = 0;
|
virtual void setMagicRulesForMimeType(const MimeType &mimeType, const QMap<int, QList<MimeMagicRule> > &rules) = 0;
|
||||||
@@ -158,8 +156,6 @@ public:
|
|||||||
|
|
||||||
// Qt Creator additions
|
// Qt Creator additions
|
||||||
void addFile(const QString &filePath);
|
void addFile(const QString &filePath);
|
||||||
QStringList bestMatchByFileName(const QString &fileName, const QList<MimeType> &types);
|
|
||||||
MimeType bestMatchByMagic(const QByteArray &data, const QList<MimeType> &types, int *accuracyPtr);
|
|
||||||
QMap<int, QList<MimeMagicRule> > magicRulesForMimeType(const MimeType &mimeType);
|
QMap<int, QList<MimeMagicRule> > magicRulesForMimeType(const MimeType &mimeType);
|
||||||
void setGlobPatternsForMimeType(const MimeType &mimeType, const QStringList &patterns);
|
void setGlobPatternsForMimeType(const MimeType &mimeType, const QStringList &patterns);
|
||||||
void setMagicRulesForMimeType(const MimeType &mimeType, const QMap<int, QList<MimeMagicRule> > &rules);
|
void setMagicRulesForMimeType(const MimeType &mimeType, const QMap<int, QList<MimeMagicRule> > &rules);
|
||||||
|
@@ -142,8 +142,9 @@ ProjectFileAdder::~ProjectFileAdder()
|
|||||||
|
|
||||||
bool ProjectFileAdder::maybeAdd(const QString &path)
|
bool ProjectFileAdder::maybeAdd(const QString &path)
|
||||||
{
|
{
|
||||||
const Utils::MimeType mt = Utils::MimeDatabase::bestMatch(path, m_mimeTypes);
|
Utils::MimeDatabase mdb;
|
||||||
if (mt.isValid()) {
|
const Utils::MimeType mt = mdb.mimeTypeForFile(path);
|
||||||
|
if (m_mimeNameMapping.contains(mt.name())) {
|
||||||
m_files << ProjectFile(path, m_mimeNameMapping.value(mt.name()));
|
m_files << ProjectFile(path, m_mimeNameMapping.value(mt.name()));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -154,10 +155,8 @@ void ProjectFileAdder::addMapping(const char *mimeName, ProjectFile::Kind kind)
|
|||||||
{
|
{
|
||||||
Utils::MimeDatabase mdb;
|
Utils::MimeDatabase mdb;
|
||||||
Utils::MimeType mimeType = mdb.mimeTypeForName(QLatin1String(mimeName));
|
Utils::MimeType mimeType = mdb.mimeTypeForName(QLatin1String(mimeName));
|
||||||
if (mimeType.isValid()) {
|
if (mimeType.isValid())
|
||||||
m_mimeNameMapping.insert(mimeType.name(), kind);
|
m_mimeNameMapping.insert(mimeType.name(), kind);
|
||||||
m_mimeTypes.append(mimeType);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
@@ -88,7 +88,6 @@ private:
|
|||||||
|
|
||||||
QList<ProjectFile> &m_files;
|
QList<ProjectFile> &m_files;
|
||||||
QHash<QString, ProjectFile::Kind> m_mimeNameMapping;
|
QHash<QString, ProjectFile::Kind> m_mimeNameMapping;
|
||||||
QList<Utils::MimeType> m_mimeTypes;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
@@ -81,14 +81,14 @@ ModelManagerInterface::ProjectInfo ModelManager::defaultProjectInfoForProject(
|
|||||||
Target *activeTarget = 0;
|
Target *activeTarget = 0;
|
||||||
if (project) {
|
if (project) {
|
||||||
MimeDatabase mdb;
|
MimeDatabase mdb;
|
||||||
QList<MimeType> qmlTypes;
|
QSet<QString> qmlTypeNames;
|
||||||
foreach (const MimeType &mimeType, mdb.allMimeTypes()) {
|
qmlTypeNames << QLatin1String(Constants::QML_MIMETYPE)
|
||||||
if (mimeType.matchesName(QLatin1String(Constants::QML_MIMETYPE))
|
<< QLatin1String(Constants::QBS_MIMETYPE)
|
||||||
|| mimeType.allAncestors().contains(QLatin1String(Constants::QML_MIMETYPE)))
|
<< QLatin1String(Constants::QMLPROJECT_MIMETYPE)
|
||||||
qmlTypes.append(mimeType);
|
<< QLatin1String(Constants::QMLTYPES_MIMETYPE)
|
||||||
}
|
<< QLatin1String(Constants::QMLUI_MIMETYPE);
|
||||||
foreach (const QString &filePath, project->files(Project::ExcludeGeneratedFiles)) {
|
foreach (const QString &filePath, project->files(Project::ExcludeGeneratedFiles)) {
|
||||||
if (mdb.bestMatch(filePath, qmlTypes).isValid())
|
if (qmlTypeNames.contains(mdb.mimeTypeForFile(filePath).name()))
|
||||||
projectInfo.sourceFiles << filePath;
|
projectInfo.sourceFiles << filePath;
|
||||||
}
|
}
|
||||||
activeTarget = project->activeTarget();
|
activeTarget = project->activeTarget();
|
||||||
|
Reference in New Issue
Block a user