Commit 38b183fd authored by Eike Ziller's avatar Eike Ziller

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: default avatarDaniel Teske <daniel.teske@theqtcompany.com>
Reviewed-by: Orgad Shaneh's avatarOrgad Shaneh <orgads@gmail.com>
parent 6758b78b
......@@ -352,79 +352,6 @@ QStringList MimeDatabase::allGlobPatterns()
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;
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 QString allFiltersString(QString *allFilesFilter = 0);
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 void setGlobPatternsForMimeType(const MimeType &mimeType, const QStringList &patterns);
static void setMagicRulesForMimeType(const MimeType &mimeType,
......
......@@ -719,38 +719,6 @@ QStringList MimeXMLProvider::findByFileName(const QString &fileName, QString *fo
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)
{
ensureLoaded();
......@@ -769,30 +737,6 @@ MimeType MimeXMLProvider::findByMagic(const QByteArray &data, int *accuracyPtr)
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> > result;
......
......@@ -75,8 +75,6 @@ public:
virtual void loadGenericIcon(MimeTypePrivate &) {}
// 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 void setGlobPatternsForMimeType(const MimeType &mimeType, const QStringList &patterns) = 0;
virtual void setMagicRulesForMimeType(const MimeType &mimeType, const QMap<int, QList<MimeMagicRule> > &rules) = 0;
......@@ -158,8 +156,6 @@ public:
// Qt Creator additions
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);
void setGlobPatternsForMimeType(const MimeType &mimeType, const QStringList &patterns);
void setMagicRulesForMimeType(const MimeType &mimeType, const QMap<int, QList<MimeMagicRule> > &rules);
......
......@@ -142,8 +142,9 @@ ProjectFileAdder::~ProjectFileAdder()
bool ProjectFileAdder::maybeAdd(const QString &path)
{
const Utils::MimeType mt = Utils::MimeDatabase::bestMatch(path, m_mimeTypes);
if (mt.isValid()) {
Utils::MimeDatabase mdb;
const Utils::MimeType mt = mdb.mimeTypeForFile(path);
if (m_mimeNameMapping.contains(mt.name())) {
m_files << ProjectFile(path, m_mimeNameMapping.value(mt.name()));
return true;
}
......@@ -154,10 +155,8 @@ void ProjectFileAdder::addMapping(const char *mimeName, ProjectFile::Kind kind)
{
Utils::MimeDatabase mdb;
Utils::MimeType mimeType = mdb.mimeTypeForName(QLatin1String(mimeName));
if (mimeType.isValid()) {
if (mimeType.isValid())
m_mimeNameMapping.insert(mimeType.name(), kind);
m_mimeTypes.append(mimeType);
}
}
} // namespace Internal
......
......@@ -88,7 +88,6 @@ private:
QList<ProjectFile> &m_files;
QHash<QString, ProjectFile::Kind> m_mimeNameMapping;
QList<Utils::MimeType> m_mimeTypes;
};
} // namespace Internal
......
......@@ -81,14 +81,14 @@ ModelManagerInterface::ProjectInfo ModelManager::defaultProjectInfoForProject(
Target *activeTarget = 0;
if (project) {
MimeDatabase mdb;
QList<MimeType> qmlTypes;
foreach (const MimeType &mimeType, mdb.allMimeTypes()) {
if (mimeType.matchesName(QLatin1String(Constants::QML_MIMETYPE))
|| mimeType.allAncestors().contains(QLatin1String(Constants::QML_MIMETYPE)))
qmlTypes.append(mimeType);
}
QSet<QString> qmlTypeNames;
qmlTypeNames << QLatin1String(Constants::QML_MIMETYPE)
<< QLatin1String(Constants::QBS_MIMETYPE)
<< QLatin1String(Constants::QMLPROJECT_MIMETYPE)
<< QLatin1String(Constants::QMLTYPES_MIMETYPE)
<< QLatin1String(Constants::QMLUI_MIMETYPE);
foreach (const QString &filePath, project->files(Project::ExcludeGeneratedFiles)) {
if (mdb.bestMatch(filePath, qmlTypes).isValid())
if (qmlTypeNames.contains(mdb.mimeTypeForFile(filePath).name()))
projectInfo.sourceFiles << filePath;
}
activeTarget = project->activeTarget();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment