C++: Use correct features for document parsing

Task-number: QTCREATORBUG-8007
Change-Id: Ic96aaa433442812a99bac9d16bb9124d66762e8c
Reviewed-by: Nikolai Kosjar <nikolai.kosjar@theqtcompany.com>
This commit is contained in:
Orgad Shaneh
2015-02-15 23:43:26 +02:00
committed by Orgad Shaneh
parent 97cbfb95bb
commit f3a2795c3b
12 changed files with 77 additions and 9 deletions

View File

@@ -396,6 +396,12 @@ public:
struct LanguageFeatures struct LanguageFeatures
{ {
LanguageFeatures() : flags(0) {} LanguageFeatures() : flags(0) {}
static LanguageFeatures defaultFeatures()
{
LanguageFeatures features;
features.flags = 0xffffffff; // Enable all flags
return features;
}
union { union {
unsigned int flags; unsigned int flags;

View File

@@ -283,15 +283,8 @@ Document::Document(const QString &fileName)
const QByteArray localFileName = fileName.toUtf8(); const QByteArray localFileName = fileName.toUtf8();
const StringLiteral *fileId = _control->stringLiteral(localFileName.constData(), const StringLiteral *fileId = _control->stringLiteral(localFileName.constData(),
localFileName.size()); localFileName.size());
LanguageFeatures features;
features.qtEnabled = true;
features.qtMocRunEnabled = true;
features.qtKeywordsEnabled = true;
features.cxx11Enabled = true;
features.objCEnabled = true;
features.c99Enabled = true;
_translationUnit = new TranslationUnit(_control, fileId); _translationUnit = new TranslationUnit(_control, fileId);
_translationUnit->setLanguageFeatures(features); _translationUnit->setLanguageFeatures(LanguageFeatures::defaultFeatures());
(void) _control->switchTranslationUnit(_translationUnit); (void) _control->switchTranslationUnit(_translationUnit);
} }
@@ -596,6 +589,19 @@ void Document::setUtf8Source(const QByteArray &source)
_translationUnit->setSource(_source.constBegin(), _source.size()); _translationUnit->setSource(_source.constBegin(), _source.size());
} }
LanguageFeatures Document::languageFeatures() const
{
if (TranslationUnit *tu = translationUnit())
return tu->languageFeatures();
return LanguageFeatures::defaultFeatures();
}
void Document::setLanguageFeatures(LanguageFeatures features)
{
if (TranslationUnit *tu = translationUnit())
tu->setLanguageFeatures(features);
}
void Document::startSkippingBlocks(unsigned utf16charsOffset) void Document::startSkippingBlocks(unsigned utf16charsOffset)
{ {
_skippedBlocks.append(Block(0, 0, utf16charsOffset, 0)); _skippedBlocks.append(Block(0, 0, utf16charsOffset, 0));
@@ -767,6 +773,7 @@ Document::Ptr Snapshot::preprocessedDocument(const QByteArray &source,
newDoc->_lastModified = thisDocument->_lastModified; newDoc->_lastModified = thisDocument->_lastModified;
newDoc->_resolvedIncludes = thisDocument->_resolvedIncludes; newDoc->_resolvedIncludes = thisDocument->_resolvedIncludes;
newDoc->_unresolvedIncludes = thisDocument->_unresolvedIncludes; newDoc->_unresolvedIncludes = thisDocument->_unresolvedIncludes;
newDoc->setLanguageFeatures(thisDocument->languageFeatures());
} }
FastPreprocessor pp(*this); FastPreprocessor pp(*this);
@@ -788,6 +795,7 @@ Document::Ptr Snapshot::documentFromSource(const QByteArray &preprocessedCode,
newDoc->_unresolvedIncludes = thisDocument->_unresolvedIncludes; newDoc->_unresolvedIncludes = thisDocument->_unresolvedIncludes;
newDoc->_definedMacros = thisDocument->_definedMacros; newDoc->_definedMacros = thisDocument->_definedMacros;
newDoc->_macroUses = thisDocument->_macroUses; newDoc->_macroUses = thisDocument->_macroUses;
newDoc->setLanguageFeatures(thisDocument->languageFeatures());
} }
newDoc->setUtf8Source(preprocessedCode); newDoc->setUtf8Source(preprocessedCode);

View File

@@ -115,6 +115,9 @@ public:
void setFingerprint(const QByteArray &fingerprint) void setFingerprint(const QByteArray &fingerprint)
{ m_fingerprint = fingerprint; } { m_fingerprint = fingerprint; }
LanguageFeatures languageFeatures() const;
void setLanguageFeatures(LanguageFeatures features);
void startSkippingBlocks(unsigned utf16charsOffset); void startSkippingBlocks(unsigned utf16charsOffset);
void stopSkippingBlocks(unsigned utf16charsOffset); void stopSkippingBlocks(unsigned utf16charsOffset);

View File

@@ -304,6 +304,7 @@ void PchManager::doPchInfoUpdateFuzzy(QFutureInterface<void> &future,
projectPart->languageVersion = languageVersions[pch]; projectPart->languageVersion = languageVersions[pch];
projectPart->languageExtensions = languageExtensionsMap[pch]; projectPart->languageExtensions = languageExtensionsMap[pch];
projectPart->headerPaths = headers[pch].toList(); projectPart->headerPaths = headers[pch].toList();
projectPart->updateLanguageFeatures();
QList<QByteArray> defines = definesPerPCH[pch].toList(); QList<QByteArray> defines = definesPerPCH[pch].toList();
if (!defines.isEmpty()) { if (!defines.isEmpty()) {
@@ -386,6 +387,7 @@ void PchManager::doPchInfoUpdateCustom(QFutureInterface<void> &future,
objc |= hasObjCFiles(projectPart); objc |= hasObjCFiles(projectPart);
cplusplus |= hasCppFiles(projectPart); cplusplus |= hasCppFiles(projectPart);
} }
united->updateLanguageFeatures();
united->headerPaths = headers; united->headerPaths = headers;
QStringList opts = Utils::createClangOptions( QStringList opts = Utils::createClangOptions(
united, getPrefixFileKind(objc, cplusplus)); united, getPrefixFileKind(objc, cplusplus));

View File

@@ -60,6 +60,7 @@ void BuiltinEditorDocumentParser::update(WorkingCopy workingCopy)
ProjectPart::HeaderPaths headerPaths; ProjectPart::HeaderPaths headerPaths;
QStringList precompiledHeaders; QStringList precompiledHeaders;
QString projectConfigFile; QString projectConfigFile;
LanguageFeatures features = LanguageFeatures::defaultFeatures();
updateProjectPart(); updateProjectPart();
@@ -75,6 +76,7 @@ void BuiltinEditorDocumentParser::update(WorkingCopy workingCopy)
projectConfigFile = part->projectConfigFile; projectConfigFile = part->projectConfigFile;
if (usePrecompiledHeaders()) if (usePrecompiledHeaders())
precompiledHeaders = part->precompiledHeaders; precompiledHeaders = part->precompiledHeaders;
features = part->languageFeatures;
} }
if (configFile != m_configFile) { if (configFile != m_configFile) {
@@ -169,6 +171,7 @@ void BuiltinEditorDocumentParser::update(WorkingCopy workingCopy)
sourceProcessor.setGlobalSnapshot(globalSnapshot); sourceProcessor.setGlobalSnapshot(globalSnapshot);
sourceProcessor.setWorkingCopy(workingCopy); sourceProcessor.setWorkingCopy(workingCopy);
sourceProcessor.setHeaderPaths(m_headerPaths); sourceProcessor.setHeaderPaths(m_headerPaths);
sourceProcessor.setLanguageFeatures(features);
sourceProcessor.run(configurationFileName); sourceProcessor.run(configurationFileName);
if (!m_projectConfigFile.isEmpty()) if (!m_projectConfigFile.isEmpty())
sourceProcessor.run(m_projectConfigFile); sourceProcessor.run(m_projectConfigFile);

View File

@@ -208,6 +208,8 @@ void index(QFutureInterface<void> &future, const ParseParams params)
CppModelManager *cmm = CppModelManager::instance(); CppModelManager *cmm = CppModelManager::instance();
const ProjectPart::HeaderPaths fallbackHeaderPaths = cmm->headerPaths(); const ProjectPart::HeaderPaths fallbackHeaderPaths = cmm->headerPaths();
const CPlusPlus::LanguageFeatures defaultFeatures =
CPlusPlus::LanguageFeatures::defaultFeatures();
for (int i = 0; i < files.size(); ++i) { for (int i = 0; i < files.size(); ++i) {
if (future.isPaused()) if (future.isPaused())
future.waitForResume(); future.waitForResume();
@@ -216,6 +218,11 @@ void index(QFutureInterface<void> &future, const ParseParams params)
break; break;
const QString fileName = files.at(i); const QString fileName = files.at(i);
const QList<ProjectPart::Ptr> parts = cmm->projectPart(fileName);
const CPlusPlus::LanguageFeatures languageFeatures = parts.isEmpty()
? defaultFeatures
: parts.first()->languageFeatures;
sourceProcessor->setLanguageFeatures(languageFeatures);
const bool isSourceFile = i < sourceCount; const bool isSourceFile = i < sourceCount;
if (isSourceFile) { if (isSourceFile) {
@@ -226,7 +233,6 @@ void index(QFutureInterface<void> &future, const ParseParams params)
processingHeaders = true; processingHeaders = true;
} }
QList<ProjectPart::Ptr> parts = cmm->projectPart(fileName);
ProjectPart::HeaderPaths headerPaths = parts.isEmpty() ProjectPart::HeaderPaths headerPaths = parts.isEmpty()
? fallbackHeaderPaths ? fallbackHeaderPaths
: parts.first()->headerPaths; : parts.first()->headerPaths;

View File

@@ -840,6 +840,7 @@ ProjectPart::Ptr CppModelManager::fallbackProjectPart() const
part->languageVersion = ProjectPart::CXX14; part->languageVersion = ProjectPart::CXX14;
part->languageExtensions = ProjectPart::AllExtensions; part->languageExtensions = ProjectPart::AllExtensions;
part->qtVersion = ProjectPart::Qt5; part->qtVersion = ProjectPart::Qt5;
part->updateLanguageFeatures();
return part; return part;
} }

View File

@@ -108,6 +108,29 @@ void ProjectPart::evaluateToolchain(const ToolChain *tc,
} }
toolchainDefines = tc->predefinedMacros(commandLineFlags); toolchainDefines = tc->predefinedMacros(commandLineFlags);
updateLanguageFeatures();
}
void ProjectPart::updateLanguageFeatures()
{
const bool hasQt = qtVersion != NoQt;
languageFeatures.cxx11Enabled = languageVersion >= CXX11;
languageFeatures.qtEnabled = hasQt;
languageFeatures.qtMocRunEnabled = hasQt;
if (!hasQt) {
languageFeatures.qtKeywordsEnabled = false;
} else {
const QByteArray noKeywordsMacro = "#define QT_NO_KEYWORDS";
const int noKeywordsIndex = projectDefines.indexOf(noKeywordsMacro);
if (noKeywordsIndex == -1) {
languageFeatures.qtKeywordsEnabled = true;
} else {
const char nextChar = projectDefines.at(noKeywordsIndex + noKeywordsMacro.length());
// Detect "#define QT_NO_KEYWORDS" and "#define QT_NO_KEYWORDS 1", but exclude
// "#define QT_NO_KEYWORDS_FOO"
languageFeatures.qtKeywordsEnabled = nextChar != '\n' && nextChar != ' ';
}
}
} }
ProjectPart::Ptr ProjectPart::copy() const ProjectPart::Ptr ProjectPart::copy() const
@@ -198,6 +221,7 @@ void ProjectInfo::finish()
QSet<HeaderPath> incs; QSet<HeaderPath> incs;
foreach (const ProjectPart::Ptr &part, m_projectParts) { foreach (const ProjectPart::Ptr &part, m_projectParts) {
part->updateLanguageFeatures();
// Update header paths // Update header paths
foreach (const HeaderPath &hp, part->headerPaths) { foreach (const HeaderPath &hp, part->headerPaths) {
if (!incs.contains(hp)) { if (!incs.contains(hp)) {

View File

@@ -38,6 +38,8 @@
#include <projectexplorer/project.h> #include <projectexplorer/project.h>
#include <projectexplorer/toolchain.h> #include <projectexplorer/toolchain.h>
#include <cplusplus/Token.h>
#include <QPointer> #include <QPointer>
#include <QSet> #include <QSet>
@@ -109,6 +111,7 @@ public: // methods
const QStringList &commandLineFlags, const QStringList &commandLineFlags,
const Utils::FileName &sysRoot); const Utils::FileName &sysRoot);
void updateLanguageFeatures();
Ptr copy() const; Ptr copy() const;
QString id() const; QString id() const;
@@ -127,6 +130,7 @@ public: // fields
QStringList precompiledHeaders; QStringList precompiledHeaders;
LanguageVersion languageVersion; LanguageVersion languageVersion;
LanguageExtensions languageExtensions; LanguageExtensions languageExtensions;
CPlusPlus::LanguageFeatures languageFeatures;
QtVersion qtVersion; QtVersion qtVersion;
ProjectExplorer::ToolChain::WarningFlags warningFlags; ProjectExplorer::ToolChain::WarningFlags warningFlags;
bool selectedForBuilding; bool selectedForBuilding;

View File

@@ -116,6 +116,7 @@ CppSourceProcessor::CppSourceProcessor(const Snapshot &snapshot, DocumentCallbac
: m_snapshot(snapshot), : m_snapshot(snapshot),
m_documentFinished(documentFinished), m_documentFinished(documentFinished),
m_preprocess(this, &m_env), m_preprocess(this, &m_env),
m_languageFeatures(LanguageFeatures::defaultFeatures()),
m_revision(0), m_revision(0),
m_defaultCodec(Core::EditorManager::defaultTextCodec()) m_defaultCodec(Core::EditorManager::defaultTextCodec())
{ {
@@ -145,6 +146,11 @@ void CppSourceProcessor::setHeaderPaths(const ProjectPart::HeaderPaths &headerPa
} }
} }
void CppSourceProcessor::setLanguageFeatures(const LanguageFeatures languageFeatures)
{
m_languageFeatures = languageFeatures;
}
// Add the given framework path, and expand private frameworks. // Add the given framework path, and expand private frameworks.
// //
// Example: // Example:
@@ -466,6 +472,7 @@ void CppSourceProcessor::sourceNeeded(unsigned line, const QString &fileName, In
Document::Ptr document = Document::create(absoluteFileName); Document::Ptr document = Document::create(absoluteFileName);
document->setRevision(m_revision); document->setRevision(m_revision);
document->setEditorRevision(editorRevision); document->setEditorRevision(editorRevision);
document->setLanguageFeatures(m_languageFeatures);
foreach (const QString &include, initialIncludes) { foreach (const QString &include, initialIncludes) {
m_included.insert(include); m_included.insert(include);
Document::Include inc(include, include, 0, IncludeLocal); Document::Include inc(include, include, 0, IncludeLocal);

View File

@@ -68,6 +68,7 @@ public:
void setRevision(unsigned revision); void setRevision(unsigned revision);
void setWorkingCopy(const CppTools::WorkingCopy &workingCopy); void setWorkingCopy(const CppTools::WorkingCopy &workingCopy);
void setHeaderPaths(const ProjectPart::HeaderPaths &headerPaths); void setHeaderPaths(const ProjectPart::HeaderPaths &headerPaths);
void setLanguageFeatures(CPlusPlus::LanguageFeatures languageFeatures);
void setTodo(const QSet<QString> &files); void setTodo(const QSet<QString> &files);
void run(const QString &fileName, const QStringList &initialIncludes = QStringList()); void run(const QString &fileName, const QStringList &initialIncludes = QStringList());
@@ -117,6 +118,7 @@ private:
CPlusPlus::Environment m_env; CPlusPlus::Environment m_env;
CPlusPlus::Preprocessor m_preprocess; CPlusPlus::Preprocessor m_preprocess;
ProjectPart::HeaderPaths m_headerPaths; ProjectPart::HeaderPaths m_headerPaths;
CPlusPlus::LanguageFeatures m_languageFeatures;
CppTools::WorkingCopy m_workingCopy; CppTools::WorkingCopy m_workingCopy;
QSet<QString> m_included; QSet<QString> m_included;
CPlusPlus::Document::Ptr m_currentDoc; CPlusPlus::Document::Ptr m_currentDoc;

View File

@@ -538,6 +538,8 @@ void QmakeProject::updateCppCodeModel()
// part->precompiledHeaders // part->precompiledHeaders
templatePart->precompiledHeaders.append(pro->variableValue(PrecompiledHeaderVar)); templatePart->precompiledHeaders.append(pro->variableValue(PrecompiledHeaderVar));
templatePart->updateLanguageFeatures();
ProjectPart::Ptr cppPart = templatePart->copy(); ProjectPart::Ptr cppPart = templatePart->copy();
{ // C++ files: { // C++ files:
// part->files // part->files