diff options
-rw-r--r-- | src/plugins/cppeditor/cppeditor.pro | 3 | ||||
-rw-r--r-- | src/plugins/cppeditor/cppeditor.qbs | 1 | ||||
-rw-r--r-- | src/plugins/cppeditor/cppeditorplugin.h | 23 | ||||
-rw-r--r-- | src/plugins/cppeditor/followsymbolundercursor_test.cpp | 801 | ||||
-rw-r--r-- | src/plugins/cpptools/cpptoolseditorsupport.cpp | 10 | ||||
-rw-r--r-- | src/plugins/cpptools/cpptoolseditorsupport.h | 3 |
6 files changed, 840 insertions, 1 deletions
diff --git a/src/plugins/cppeditor/cppeditor.pro b/src/plugins/cppeditor/cppeditor.pro index 9577e1debf..60207dd717 100644 --- a/src/plugins/cppeditor/cppeditor.pro +++ b/src/plugins/cppeditor/cppeditor.pro @@ -42,7 +42,8 @@ equals(TEST, 1) { SOURCES += \ cppquickfix_test.cpp \ cppdoxygen_test.cpp \ - fileandtokenactions_test.cpp + fileandtokenactions_test.cpp \ + followsymbolundercursor_test.cpp DEFINES += SRCDIR=\\\"$$PWD\\\" } diff --git a/src/plugins/cppeditor/cppeditor.qbs b/src/plugins/cppeditor/cppeditor.qbs index e4cf86123f..95ce87a83f 100644 --- a/src/plugins/cppeditor/cppeditor.qbs +++ b/src/plugins/cppeditor/cppeditor.qbs @@ -61,6 +61,7 @@ QtcPlugin { "cppdoxygen_test.cpp", "cppquickfix_test.cpp", "fileandtokenactions_test.cpp", + "followsymbolundercursor_test.cpp" ] cpp.defines: outer.concat(['SRCDIR="' + FileInfo.path(filePath) + '"']) diff --git a/src/plugins/cppeditor/cppeditorplugin.h b/src/plugins/cppeditor/cppeditorplugin.h index 6312d8629d..9fe08d1289 100644 --- a/src/plugins/cppeditor/cppeditorplugin.h +++ b/src/plugins/cppeditor/cppeditorplugin.h @@ -93,6 +93,29 @@ private slots: #ifdef WITH_TESTS private slots: // The following tests expect that no projects are loaded on start-up. + void test_FollowSymbolUnderCursor_globalVarFromFunction(); + void test_FollowSymbolUnderCursor_funLocalVarHidesClassMember(); + void test_FollowSymbolUnderCursor_funLocalVarHidesNamespaceMemberIntroducedByUsingDirective(); + void test_FollowSymbolUnderCursor_loopLocalVarHidesOuterScopeVariable1(); + void test_FollowSymbolUnderCursor_loopLocalVarHidesOuterScopeVariable2(); + void test_FollowSymbolUnderCursor_subsequentDefinedClassMember(); + void test_FollowSymbolUnderCursor_classMemberHidesOuterTypeDef(); + void test_FollowSymbolUnderCursor_globalVarFromEnum(); + void test_FollowSymbolUnderCursor_selfInitialization(); + void test_FollowSymbolUnderCursor_pointerToClassInClassDefinition(); + void test_FollowSymbolUnderCursor_previouslyDefinedMemberFromArrayDefinition(); + void test_FollowSymbolUnderCursor_outerStaticMemberVariableFromInsideSubclass(); + void test_FollowSymbolUnderCursor_memberVariableFollowingDotOperator(); + void test_FollowSymbolUnderCursor_memberVariableFollowingArrowOperator(); + void test_FollowSymbolUnderCursor_staticMemberVariableFollowingScopeOperator(); + void test_FollowSymbolUnderCursor_staticMemberVariableFollowingDotOperator(); + void test_FollowSymbolUnderCursor_staticMemberVariableFollowingArrowOperator(); + void test_FollowSymbolUnderCursor_previouslyDefinedEnumValueFromInsideEnum(); + void test_FollowSymbolUnderCursor_nsMemberHidesNsMemberIntroducedByUsingDirective(); + void test_FollowSymbolUnderCursor_baseClassFunctionIntroducedByUsingDeclaration(); + void test_FollowSymbolUnderCursor_funWithSameNameAsBaseClassFunIntroducedByUsingDeclaration(); + void test_FollowSymbolUnderCursor_funLocalVarHidesOuterClass(); + void test_doxygen_comments_qt_style(); void test_doxygen_comments_qt_style_continuation(); void test_doxygen_comments_java_style(); diff --git a/src/plugins/cppeditor/followsymbolundercursor_test.cpp b/src/plugins/cppeditor/followsymbolundercursor_test.cpp new file mode 100644 index 0000000000..03f06899aa --- /dev/null +++ b/src/plugins/cppeditor/followsymbolundercursor_test.cpp @@ -0,0 +1,801 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "cppeditor.h" +#include "cppeditorplugin.h" + +#include <cpptools/cpptoolseditorsupport.h> + +#include <utils/fileutils.h> + +#include <QDebug> +#include <QDir> +#include <QtTest> + + +/*! + Tests for Follow Symbol Under Cursor + + Section numbers refer to + + Working Draft, Standard for Programming Language C++ + Document Number: N3242=11-0012 + + You can find potential test code on the bottom of this file. + */ +using namespace CPlusPlus; +using namespace CppEditor; +using namespace CppEditor::Internal; +using namespace CppTools; +using namespace TextEditor; +using namespace Core; + +namespace { + +class TestDocument; +typedef QSharedPointer<TestDocument> TestDocumentPtr; + +/** + * Represents a test document. + * + * A TestDocument's source can contain special characters: + * - a '@' character denotes the initial text cursor position + * - a '$' character denotes the target text cursor position + */ +class TestDocument +{ +public: + TestDocument(const QByteArray &theSource, const QString &fileName) + : source(theSource) + , fileName(fileName) + , initialCursorPosition(source.indexOf('@')) + , targetCursorPosition(source.indexOf('$')) + , editor(0) + , editorWidget(0) + , editorSupport(0) + { + QVERIFY(initialCursorPosition != targetCursorPosition); + if (initialCursorPosition > targetCursorPosition) { + source.remove(initialCursorPosition, 1); + source.remove(targetCursorPosition, 1); + --initialCursorPosition; + } else { + source.remove(targetCursorPosition, 1); + source.remove(initialCursorPosition, 1); + --targetCursorPosition; + } + } + + static TestDocumentPtr create(const QByteArray &theOriginalSource, const QString &fileName) + { + return TestDocumentPtr(new TestDocument(theOriginalSource, fileName)); + } + + bool hasInitialCursorMarker() const { return initialCursorPosition != -1; } + bool hasTargetCursorMarker() const { return targetCursorPosition != -1; } + + QString filePath() const + { + if (directoryPath.isEmpty()) + qDebug() << "directoryPath not set!"; + return directoryPath + QLatin1Char('/') + fileName; + } + + void writeToDisk() const + { + Utils::FileSaver srcSaver(filePath()); + srcSaver.write(source); + srcSaver.finalize(); + } + + QByteArray source; + + const QString fileName; + QString directoryPath; + int initialCursorPosition; + int targetCursorPosition; + + CPPEditor *editor; + CPPEditorWidget *editorWidget; + CppEditorSupport *editorSupport; +}; + +/** + * Encapsulates the whole process of setting up several editors, positioning the cursor, + * executing Follow Symbol Under Cursor and checking the result. + */ +struct TestCase +{ + QList<TestDocumentPtr> testFiles; + + TestCase(const QByteArray &source); + TestCase(const QList<TestDocumentPtr> theTestFiles); + ~TestCase(); + + void run(); + +private: + TestCase(const TestCase &); + TestCase &operator=(const TestCase &); + + void init(); + + TestDocumentPtr testFileWithInitialCursorMarker(); + TestDocumentPtr testFileWithTargetCursorMarker(); +}; + +/// Convenience function for creating a TestDocument. +/// See TestDocument. +TestCase::TestCase(const QByteArray &source) +{ + testFiles << TestDocument::create(source, QLatin1String("file.cpp")); + init(); +} + +/// Creates a test case with multiple test files. +/// Exactly one test document must be provided that contains '@', the initial position marker. +/// Exactly one test document must be provided that contains '$', the target position marker. +/// It can be the same document. +TestCase::TestCase(const QList<TestDocumentPtr> theTestFiles) + : testFiles(theTestFiles) +{ + init(); +} + +void TestCase::init() +{ + // Check if there are initial and target position markers + QVERIFY2(testFileWithInitialCursorMarker(), + "No test file with initial cursor marker is provided."); + QVERIFY2(testFileWithTargetCursorMarker(), + "No test file with target cursor marker is provided."); + + // Write files to disk + const QString directoryPath = QDir::tempPath(); + foreach (TestDocumentPtr testFile, testFiles) { + testFile->directoryPath = directoryPath; + testFile->writeToDisk(); + } + + // Update Code Model + QStringList filePaths; + foreach (const TestDocumentPtr &testFile, testFiles) + filePaths << testFile->filePath(); + CppTools::CppModelManagerInterface::instance()->updateSourceFiles(filePaths); + + // Wait for the indexer to process all files. + // All these files are "Fast Checked", that is the function bodies are not processed. + QStringList filePathsNotYetInSnapshot(filePaths); + forever { + Snapshot snapshot = CppTools::CppModelManagerInterface::instance()->snapshot(); + foreach (const QString &filePath, filePathsNotYetInSnapshot) { + if (snapshot.contains(filePath)) + filePathsNotYetInSnapshot.removeOne(filePath); + } + if (filePathsNotYetInSnapshot.isEmpty()) + break; + QCoreApplication::processEvents(); + } + + // Open Files + foreach (TestDocumentPtr testFile, testFiles) { + testFile->editor + = dynamic_cast<CPPEditor *>(EditorManager::openEditor(testFile->filePath())); + QVERIFY(testFile->editor); + + testFile->editorWidget = dynamic_cast<CPPEditorWidget *>(testFile->editor->editorWidget()); + QVERIFY(testFile->editorWidget); + + // Wait until the indexer processed the just opened file. + // The file is "Full Checked" (it's in the working copy now), + // that is the function bodies are processed. + CppModelManagerInterface *mmi = CppTools::CppModelManagerInterface::instance(); + testFile->editorSupport = mmi->cppEditorSupport(testFile->editor); + QVERIFY(testFile->editorSupport); + while (testFile->editorSupport->isDocumentBeingUpdated() + || testFile->editorSupport->isDocumentScheduledForUpdate()) { + QCoreApplication::processEvents(); + } + + // Rehighlight + testFile->editorWidget->semanticRehighlight(true); + // Wait for the semantic info from the future + while (testFile->editorWidget->semanticInfo().doc.isNull()) + QCoreApplication::processEvents(); + } +} + +TestCase::~TestCase() +{ + // Close editors + QList<Core::IEditor *> editorsToClose; + foreach (const TestDocumentPtr testFile, testFiles) { + if (testFile->editor) + editorsToClose << testFile->editor; + } + EditorManager::instance()->closeEditors(editorsToClose, false); + QCoreApplication::processEvents(); // process any pending events + + // Remove the test files from the code-model + CppModelManagerInterface *mmi = CppTools::CppModelManagerInterface::instance(); + mmi->GC(); + QCOMPARE(mmi->snapshot().size(), 0); +} + +TestDocumentPtr TestCase::testFileWithInitialCursorMarker() +{ + foreach (const TestDocumentPtr testFile, testFiles) { + if (testFile->hasInitialCursorMarker()) + return testFile; + } + return TestDocumentPtr(); +} + +TestDocumentPtr TestCase::testFileWithTargetCursorMarker() +{ + foreach (const TestDocumentPtr testFile, testFiles) { + if (testFile->hasTargetCursorMarker()) + return testFile; + } + return TestDocumentPtr(); +} + +void TestCase::run() +{ + TestDocumentPtr initialTestFile = testFileWithInitialCursorMarker(); + QVERIFY(initialTestFile); + TestDocumentPtr targetTestFile = testFileWithTargetCursorMarker(); + QVERIFY(targetTestFile); + + // Trigger Follow Symbol Under Cursor + initialTestFile->editor->setCursorPosition(initialTestFile->initialCursorPosition); +// qDebug() << "Initial line:" << initialTestFile->editor->currentLine(); +// qDebug() << "Initial column:" << initialTestFile->editor->currentColumn() - 1; + initialTestFile->editorWidget->openLinkUnderCursor(); + + QCoreApplication::processEvents(); + + // Compare + IEditor *currentEditor = EditorManager::instance()->currentEditor(); + BaseTextEditor *currentTextEditor = dynamic_cast<BaseTextEditor*>(currentEditor); + QVERIFY(currentTextEditor); + + QCOMPARE(currentTextEditor->document()->fileName(), targetTestFile->filePath()); + int expectedLine, expectedColumn; + currentTextEditor->convertPosition(targetTestFile->targetCursorPosition, + &expectedLine, &expectedColumn); +// qDebug() << "Expected line:" << expectedLine; +// qDebug() << "Expected column:" << expectedColumn; + QCOMPARE(currentTextEditor->currentLine(), expectedLine); + QCOMPARE(currentTextEditor->currentColumn() - 1, expectedColumn); +} + +} // anonymous namespace + +/// Check ... +void CppEditorPlugin::test_FollowSymbolUnderCursor_globalVarFromFunction() +{ + const QByteArray source = + "int $j;\n" + "int main()\n" + "{\n" + " @j = 2;\n" + "}\n" // Line 5 + ; + + TestCase data(source); + data.run(); +} + +void CppEditorPlugin::test_FollowSymbolUnderCursor_funLocalVarHidesClassMember() +{ + // 3.3.10 Name hiding (par 3.), from text + const QByteArray source = + "struct C {\n" + " void f()\n" + " {\n" + " int $member; // hides C::member\n" + " ++@member;\n" // Line 5 + " }\n" + " int member;\n" + "};\n" + ; + + TestCase data(source); + data.run(); +} + +void CppEditorPlugin::test_FollowSymbolUnderCursor_funLocalVarHidesNamespaceMemberIntroducedByUsingDirective() +{ + // 3.3.10 Name hiding (par 4.), from text + const QByteArray source = + "namespace N {\n" + " int i;\n" + "}\n" + "\n" + "int main()\n" // Line 5 + "{\n" + " using namespace N;\n" + " int $i;\n" + " ++i@; // refers to local i;\n" + "}\n" // Line 10 + ; + + TestCase data(source); + data.run(); +} + +void CppEditorPlugin::test_FollowSymbolUnderCursor_loopLocalVarHidesOuterScopeVariable1() +{ + // 3.3.3 Block scope (par. 4), from text + // Same for if, while, switch + const QByteArray source = + "int main()\n" + "{\n" + " int i = 1;\n" + " for (int $i = 0; i < 10; ++i) { // 'i' refers to for's i\n" + " i = @i; // same\n" // Line 5 + " }\n" + "}\n"; + ; + + TestCase data(source); + data.run(); +} + +void CppEditorPlugin::test_FollowSymbolUnderCursor_loopLocalVarHidesOuterScopeVariable2() +{ + // 3.3.3 Block scope (par. 4), from text + // Same for if, while, switch + const QByteArray source = + "int main()\n" + "{\n" + " int i = 1;\n" + " for (int $i = 0; @i < 10; ++i) { // 'i' refers to for's i\n" + " i = i; // same\n" // Line 5 + " }\n" + "}\n"; + ; + + TestCase data(source); + data.run(); +} + +void CppEditorPlugin::test_FollowSymbolUnderCursor_subsequentDefinedClassMember() +{ + // 3.3.7 Class scope, part of the example + const QByteArray source = + "class X {\n" + " int f() { return @i; } // i refers to class's i\n" + " int $i;\n" + "};\n" + ; + + TestCase data(source); + data.run(); +} + +void CppEditorPlugin::test_FollowSymbolUnderCursor_classMemberHidesOuterTypeDef() +{ + // 3.3.7 Class scope, part of the example + // Variable name hides type name. + const QByteArray source = + "typedef int c;\n" + "class X {\n" + " int f() { return @c; } // c refers to class' c\n" + " int $c; // hides typedef name\n" + "};\n" // Line 5 + ; + + TestCase data(source); + data.run(); +} + +void CppEditorPlugin::test_FollowSymbolUnderCursor_globalVarFromEnum() +{ + // 3.3.2 Point of declaration (par. 1), copy-paste + const QByteArray source = + "const int $x = 12;\n" + "int main()\n" + "{\n" + " enum { x = @x }; // x refers to global x\n" + "}\n" // Line 5 + ; + + TestCase data(source); + data.run(); +} + +void CppEditorPlugin::test_FollowSymbolUnderCursor_selfInitialization() +{ + // 3.3.2 Point of declaration + const QByteArray source = + "int x = 12;\n" + "int main()\n" + "{\n" + " int $x = @x; // Second x refers to local x\n" + "}\n" // Line 5 + ; + + TestCase data(source); + data.run(); +} + +void CppEditorPlugin::test_FollowSymbolUnderCursor_pointerToClassInClassDefinition() +{ + // 3.3.2 Point of declaration (par. 3), from text + const QByteArray source = + "class $Foo {\n" + " @Foo *p; // Refers to above Foo\n" + "};\n" + ; + + TestCase data(source); + data.run(); +} + +void CppEditorPlugin::test_FollowSymbolUnderCursor_previouslyDefinedMemberFromArrayDefinition() +{ + // 3.3.2 Point of declaration (par. 5), copy-paste + const QByteArray source = + "struct X {\n" + " enum E { $z = 16 };\n" + " int b[X::@z]; // z refers to defined z\n" + "};\n" + ; + + TestCase data(source); + data.run(); +} + +void CppEditorPlugin::test_FollowSymbolUnderCursor_outerStaticMemberVariableFromInsideSubclass() +{ + // 3.3.7 Class scope (par. 2), from text + const QByteArray source = + "struct C\n" + "{\n" + " struct I\n" + " {\n" + " void f()\n" // Line 5 + " {\n" + " int i = @c; // refers to C's c\n" + " }\n" + " };\n" + "\n" // Line 10 + " static int $c;\n" + "};\n" + ; + + TestCase data(source); + data.run(); +} + +void CppEditorPlugin::test_FollowSymbolUnderCursor_memberVariableFollowingDotOperator() +{ + // 3.3.7 Class scope (par. 1), part of point 5 + const QByteArray source = + "struct C\n" + "{\n" + " int $member;\n" + "};\n" + "\n" // Line 5 + "int main()\n" + "{\n" + " C c;\n" + " c.@member++;\n" + "}\n" // Line 10 + ; + + TestCase data(source); + data.run(); +} + +void CppEditorPlugin::test_FollowSymbolUnderCursor_memberVariableFollowingArrowOperator() +{ + // 3.3.7 Class scope (par. 1), part of point 5 + const QByteArray source = + "struct C\n" + "{\n" + " int $member;\n" + "};\n" + "\n" // Line 5 + "int main()\n" + "{\n" + " C* c;\n" + " c->@member++;\n" + "}\n" // Line 10 + ; + + TestCase data(source); + data.run(); +} + +void CppEditorPlugin::test_FollowSymbolUnderCursor_staticMemberVariableFollowingScopeOperator() +{ + // 3.3.7 Class scope (par. 1), part of point 5 + const QByteArray source = + "struct C\n" + "{\n" + " static int $member;\n" + "};\n" + "\n" // Line 5 + "int main()\n" + "{\n" + " C::@member++;\n" + "}\n" + ; + + TestCase data(source); + data.run(); +} + +void CppEditorPlugin::test_FollowSymbolUnderCursor_staticMemberVariableFollowingDotOperator() +{ + // 3.3.7 Class scope (par. 2), from text + const QByteArray source = + "struct C\n" + "{\n" + " static int $member;\n" + "};\n" + "\n" // Line 5 + "int main()\n" + "{\n" + " C c;\n" + " c.@member;\n" + "}\n" // Line 10 + ; + + TestCase data(source); + data.run(); +} + + +void CppEditorPlugin::test_FollowSymbolUnderCursor_staticMemberVariableFollowingArrowOperator() +{ + // 3.3.7 Class scope (par. 2), from text + const QByteArray source = + "struct C\n" + "{\n" + " static int $member;\n" + "};\n" + "\n" // Line 5 + "int main()\n" + "{\n" + " C *c;\n" + " c->@member++;\n" + "}\n" // Line 10 + ; + + TestCase data(source); + data.run(); +} + +void CppEditorPlugin::test_FollowSymbolUnderCursor_previouslyDefinedEnumValueFromInsideEnum() +{ + // 3.3.8 Enumeration scope + const QByteArray source = + "enum {\n" + " $i = 0,\n" + " j = @i // refers to i above\n" + "};\n" + ; + + TestCase data(source); + data.run(); +} + +void CppEditorPlugin::test_FollowSymbolUnderCursor_nsMemberHidesNsMemberIntroducedByUsingDirective() +{ + // 3.3.8 Enumeration scope + const QByteArray source = + "namespace A {\n" + " char x;\n" + "}\n" + "\n" + "namespace B {\n" // Line 5 + " using namespace A;\n" + " int $x; // hides A::x\n" + "}\n" + "\n" + "int main()\n" // Line 10 + "{\n" + " B::@x++; // refers to B's X, not A::x\n" + "}\n" + ; + + TestCase data(source); + data.run(); +} + +void CppEditorPlugin::test_FollowSymbolUnderCursor_baseClassFunctionIntroducedByUsingDeclaration() +{ + // 3.3.10 Name hiding, from text + // www.stroustrup.com/bs_faq2.html#overloadderived + const QByteArray source = + "struct B {\n" + " int $f(int) {}\n" + "};\n" + "\n" + "class D : public B {\n" // Line 5 + "public:\n" + " using B::f; // make every f from B available\n" + " double f(double) {}\n" + "};\n" + "\n" // Line 10 + "int main()\n" + "{\n" + " D* pd = new D;\n" + " pd->@f(2); // refers to B::f\n" + " pd->f(2.3); // refers to D::f\n" // Line 15 + "}\n" + ; + + TestCase data(source); + data.run(); +} + +void CppEditorPlugin::test_FollowSymbolUnderCursor_funWithSameNameAsBaseClassFunIntroducedByUsingDeclaration() +{ + // 3.3.10 Name hiding, from text + // www.stroustrup.com/bs_faq2.html#overloadderived + const QByteArray source = + "struct B {\n" + " int f(int) {}\n" + "};\n" + "\n" + "class D : public B {\n" // Line 5 + "public:\n" + " using B::f; // make every f from B available\n" + " double $f(double) {}\n" + "};\n" + "\n" // Line 10 + "int main()\n" + "{\n" + " D* pd = new D;\n" + " pd->f(2); // refers to B::f\n" + " pd->@f(2.3); // refers to D::f\n" // Line 15 + "}\n" + ; + + TestCase data(source); + data.run(); +} + +void CppEditorPlugin::test_FollowSymbolUnderCursor_funLocalVarHidesOuterClass() +{ + // 3.3.10 Name hiding (par 2.), from text + // A class name (9.1) or enumeration name (7.2) can be hidden by the name of a variable, data member, + // function, or enumerator declared in the same scope. + const QByteArray source = + "struct C {};\n" + "\n" + "int main()\n" + "{\n" + " int $C; // hides type C\n" // Line 5 + " ++@C;\n" + "}\n" + ; + + TestCase data(source); + data.run(); +} + +/* +Potential test cases improving name lookup. + +If you fix one, add a test and remove the example from here. + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +// 3.3.1 Declarative regions and scopes, copy-paste (main added) +int j = 24; +int main() +{ + int i = j, j; // First j refers to global j, second j refers to just locally defined j + j = 42; // Refers to locally defined j +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +// 3.3.2 Point of declaration (par. 2), copy-paste (main added) +const int i = 2; +int main() +{ + int i[i]; // Second i refers to global +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +// 3.3.2 Point of declaration (par. 9), copy-paste (main added) +typedef unsigned char T; +template<class T += T // lookup finds the typedef name of unsigned char +, T // lookup finds the template parameter +N = 0> struct A { }; + +int main() {} + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +// 3.3.9 Template parameter scope (par. 3), copy-paste (main added), part 1 +template<class T, T* p, class U = T> class X {}; // second and third T refers to first one +template<class T> void f(T* p = new T); + +int main() {} + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +// 3.3.9 Template parameter scope (par. 3), copy-paste (main added), part 2 +template<class T> class X : public Array<T> {}; +template<class T> class Y : public T {}; + +int main() {} + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +// 3.3.9 Template parameter scope (par. 4), copy-paste (main added), part 2 +typedef int N; +template<N X, typename N, template<N Y> class T> struct A; // N refers to N above + +int main() {} + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +// 3.3.10 Name hiding (par 1.), from text, example 2a + +// www.stroustrup.com/bs_faq2.html#overloadderived +// "In C++, there is no overloading across scopes - derived class scopes are not +// an exception to this general rule. (See D&E or TC++PL3 for details)." +struct B { + int f(int) {} +}; + +struct D : public B { + double f(double) {} // hides B::f +}; + +int main() +{ + D* pd = new D; + pd->f(2); // refers to D::f + pd->f(2.3); // refers to D::f +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +// 3.3.10 Name hiding (par 2.), from text +int C; // hides following type C, order is not important +struct C {}; + +int main() +{ + ++C; +} + +*/ diff --git a/src/plugins/cpptools/cpptoolseditorsupport.cpp b/src/plugins/cpptools/cpptoolseditorsupport.cpp index f9e37b5190..0712355525 100644 --- a/src/plugins/cpptools/cpptoolseditorsupport.cpp +++ b/src/plugins/cpptools/cpptoolseditorsupport.cpp @@ -164,6 +164,16 @@ unsigned CppEditorSupport::editorRevision() const return m_textEditor->editorWidget()->document()->revision(); } +bool CppEditorSupport::isDocumentBeingUpdated() const +{ + return m_documentParser.isRunning(); +} + +bool CppEditorSupport::isDocumentScheduledForUpdate() const +{ + return m_updateDocumentTimer->isActive(); +} + void CppEditorSupport::setExtraDiagnostics(const QString &key, const QList<Document::DiagnosticMessage> &messages) { diff --git a/src/plugins/cpptools/cpptoolseditorsupport.h b/src/plugins/cpptools/cpptoolseditorsupport.h index d7534f33e2..64f75390bd 100644 --- a/src/plugins/cpptools/cpptoolseditorsupport.h +++ b/src/plugins/cpptools/cpptoolseditorsupport.h @@ -95,6 +95,9 @@ public: QString contents() const; unsigned editorRevision() const; + bool isDocumentBeingUpdated() const; + bool isDocumentScheduledForUpdate() const; + void setExtraDiagnostics(const QString &key, const QList<CPlusPlus::Document::DiagnosticMessage> &messages); |