summaryrefslogtreecommitdiff
path: root/tests/auto/cplusplus/codegen/tst_codegen.cpp
diff options
context:
space:
mode:
authorChristian Kamm <christian.d.kamm@nokia.com>2011-11-14 15:08:25 +0100
committerBill King <bill.king@nokia.com>2011-11-15 15:37:29 +0100
commitbc1b724476db3f7d52ad135857b693487644611f (patch)
treeb25c6573d3cd1c56631d2abea8460ff2e7f208ea /tests/auto/cplusplus/codegen/tst_codegen.cpp
parente93d685a9e8637d78dc0f6cceaf1959a8213f9e0 (diff)
downloadqt-creator-bc1b724476db3f7d52ad135857b693487644611f.tar.gz
C++: Move codegen test into the CppTools plugin.
Change-Id: I4c70a9dbd5445188c3d202427da96e1c6ff90b63 Reviewed-by: Bill King <bill.king@nokia.com>
Diffstat (limited to 'tests/auto/cplusplus/codegen/tst_codegen.cpp')
-rw-r--r--tests/auto/cplusplus/codegen/tst_codegen.cpp681
1 files changed, 0 insertions, 681 deletions
diff --git a/tests/auto/cplusplus/codegen/tst_codegen.cpp b/tests/auto/cplusplus/codegen/tst_codegen.cpp
deleted file mode 100644
index e1425f7cbe..0000000000
--- a/tests/auto/cplusplus/codegen/tst_codegen.cpp
+++ /dev/null
@@ -1,681 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-**
-** GNU Lesser General Public License Usage
-**
-** 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, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** Other Usage
-**
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**************************************************************************/
-
-#include <AST.h>
-#include <Control.h>
-#include <CppDocument.h>
-#include <DiagnosticClient.h>
-#include <Scope.h>
-#include <TranslationUnit.h>
-#include <Literals.h>
-#include <Bind.h>
-#include <Symbols.h>
-#include <cpptools/insertionpointlocator.h>
-#include <cpptools/cpprefactoringchanges.h>
-#include <cpptools/cpptoolsplugin.h>
-#include <extensionsystem/pluginmanager.h>
-#include <utils/fileutils.h>
-
-#include <QtTest>
-#include <QtDebug>
-#include <QTextDocument>
-#include <QDir>
-
-//TESTED_COMPONENT=src/libs/cplusplus
-
-/*!
- Tests for various parts of the code generation. Well, okay, currently it only
- tests the InsertionPointLocator.
- */
-using namespace CPlusPlus;
-using namespace CppTools;
-
-class tst_Codegen: public QObject
-{
- Q_OBJECT
-
-private slots:
- void initTestCase();
- void cleanupTestCase();
- void public_in_empty_class();
- void public_in_nonempty_class();
- void public_before_protected();
- void private_after_protected();
- void protected_in_nonempty_class();
- void protected_betwee_public_and_private();
- void qtdesigner_integration();
- void definition_empty_class();
- void definition_first_member();
- void definition_last_member();
- void definition_middle_member();
-
-private:
- ExtensionSystem::PluginManager *pluginManager;
- QString tempPath;
-};
-
-void tst_Codegen::initTestCase()
-{
- pluginManager = new ExtensionSystem::PluginManager;
- QSettings *settings = new QSettings(QSettings::IniFormat, QSettings::UserScope,
- QLatin1String("Nokia"), QLatin1String("QtCreator"));
- pluginManager->setSettings(settings);
- pluginManager->setFileExtension(QLatin1String("pluginspec"));
- pluginManager->setPluginPaths(QStringList() << QLatin1String(Q_PLUGIN_PATH));
- pluginManager->loadPlugins();
-
- tempPath = QDir::tempPath();
-}
-
-void tst_Codegen::cleanupTestCase()
-{
- // gives me a qFatal...
-// pluginManager->shutdown();
-// delete pluginManager;
-}
-/*!
- Should insert at line 3, column 1, with "public:\n" as prefix and without suffix.
- */
-void tst_Codegen::public_in_empty_class()
-{
- const QByteArray src = "\n"
- "class Foo\n" // line 1
- "{\n"
- "};\n"
- "\n";
-
- Document::Ptr doc = Document::create("public_in_empty_class");
- doc->setSource(src);
- doc->parse();
- doc->check();
-
- QCOMPARE(doc->diagnosticMessages().size(), 0);
- QCOMPARE(doc->globalSymbolCount(), 1U);
-
- Class *foo = doc->globalSymbolAt(0)->asClass();
- QVERIFY(foo);
- QCOMPARE(foo->line(), 1U);
- QCOMPARE(foo->column(), 7U);
-
- Snapshot snapshot;
- snapshot.insert(doc);
- CppRefactoringChanges changes(snapshot);
- InsertionPointLocator find(changes);
- InsertionLocation loc = find.methodDeclarationInClass(
- doc->fileName(),
- foo,
- InsertionPointLocator::Public);
- QVERIFY(loc.isValid());
- QCOMPARE(loc.prefix(), QLatin1String("public:\n"));
- QVERIFY(loc.suffix().isEmpty());
- QCOMPARE(loc.line(), 3U);
- QCOMPARE(loc.column(), 1U);
-}
-
-/*!
- Should insert at line 3, column 1, without prefix and without suffix.
- */
-void tst_Codegen::public_in_nonempty_class()
-{
- const QByteArray src = "\n"
- "class Foo\n" // line 1
- "{\n"
- "public:\n" // line 3
- "};\n" // line 4
- "\n";
-
- Document::Ptr doc = Document::create("public_in_nonempty_class");
- doc->setSource(src);
- doc->parse();
- doc->check();
-
- QCOMPARE(doc->diagnosticMessages().size(), 0);
- QCOMPARE(doc->globalSymbolCount(), 1U);
-
- Class *foo = doc->globalSymbolAt(0)->asClass();
- QVERIFY(foo);
- QCOMPARE(foo->line(), 1U);
- QCOMPARE(foo->column(), 7U);
-
- Snapshot snapshot;
- snapshot.insert(doc);
- CppRefactoringChanges changes(snapshot);
- InsertionPointLocator find(changes);
- InsertionLocation loc = find.methodDeclarationInClass(
- doc->fileName(),
- foo,
- InsertionPointLocator::Public);
- QVERIFY(loc.isValid());
- QVERIFY(loc.prefix().isEmpty());
- QVERIFY(loc.suffix().isEmpty());
- QCOMPARE(loc.line(), 4U);
- QCOMPARE(loc.column(), 1U);
-}
-
-/*!
- Should insert at line 3, column 1, with "public:\n" as prefix and "\n suffix.
- */
-void tst_Codegen::public_before_protected()
-{
- const QByteArray src = "\n"
- "class Foo\n" // line 1
- "{\n"
- "protected:\n" // line 3
- "};\n"
- "\n";
-
- Document::Ptr doc = Document::create("public_before_protected");
- doc->setSource(src);
- doc->parse();
- doc->check();
-
- QCOMPARE(doc->diagnosticMessages().size(), 0);
- QCOMPARE(doc->globalSymbolCount(), 1U);
-
- Class *foo = doc->globalSymbolAt(0)->asClass();
- QVERIFY(foo);
- QCOMPARE(foo->line(), 1U);
- QCOMPARE(foo->column(), 7U);
-
- Snapshot snapshot;
- snapshot.insert(doc);
- CppRefactoringChanges changes(snapshot);
- InsertionPointLocator find(changes);
- InsertionLocation loc = find.methodDeclarationInClass(
- doc->fileName(),
- foo,
- InsertionPointLocator::Public);
- QVERIFY(loc.isValid());
- QCOMPARE(loc.prefix(), QLatin1String("public:\n"));
- QCOMPARE(loc.suffix(), QLatin1String("\n"));
- QCOMPARE(loc.column(), 1U);
- QCOMPARE(loc.line(), 3U);
-}
-
-/*!
- Should insert at line 4, column 1, with "private:\n" as prefix and without
- suffix.
- */
-void tst_Codegen::private_after_protected()
-{
- const QByteArray src = "\n"
- "class Foo\n" // line 1
- "{\n"
- "protected:\n" // line 3
- "};\n"
- "\n";
-
- Document::Ptr doc = Document::create("private_after_protected");
- doc->setSource(src);
- doc->parse();
- doc->check();
-
- QCOMPARE(doc->diagnosticMessages().size(), 0);
- QCOMPARE(doc->globalSymbolCount(), 1U);
-
- Class *foo = doc->globalSymbolAt(0)->asClass();
- QVERIFY(foo);
- QCOMPARE(foo->line(), 1U);
- QCOMPARE(foo->column(), 7U);
-
- Snapshot snapshot;
- snapshot.insert(doc);
- CppRefactoringChanges changes(snapshot);
- InsertionPointLocator find(changes);
- InsertionLocation loc = find.methodDeclarationInClass(
- doc->fileName(),
- foo,
- InsertionPointLocator::Private);
- QVERIFY(loc.isValid());
- QCOMPARE(loc.prefix(), QLatin1String("private:\n"));
- QVERIFY(loc.suffix().isEmpty());
- QCOMPARE(loc.column(), 1U);
- QCOMPARE(loc.line(), 4U);
-}
-
-/*!
- Should insert at line 4, column 1, with "protected:\n" as prefix and without
- suffix.
- */
-void tst_Codegen::protected_in_nonempty_class()
-{
- const QByteArray src = "\n"
- "class Foo\n" // line 1
- "{\n"
- "public:\n" // line 3
- "};\n" // line 4
- "\n";
-
- Document::Ptr doc = Document::create("protected_in_nonempty_class");
- doc->setSource(src);
- doc->parse();
- doc->check();
-
- QCOMPARE(doc->diagnosticMessages().size(), 0);
- QCOMPARE(doc->globalSymbolCount(), 1U);
-
- Class *foo = doc->globalSymbolAt(0)->asClass();
- QVERIFY(foo);
- QCOMPARE(foo->line(), 1U);
- QCOMPARE(foo->column(), 7U);
-
- Snapshot snapshot;
- snapshot.insert(doc);
- CppRefactoringChanges changes(snapshot);
- InsertionPointLocator find(changes);
- InsertionLocation loc = find.methodDeclarationInClass(
- doc->fileName(),
- foo,
- InsertionPointLocator::Protected);
- QVERIFY(loc.isValid());
- QCOMPARE(loc.prefix(), QLatin1String("protected:\n"));
- QVERIFY(loc.suffix().isEmpty());
- QCOMPARE(loc.column(), 1U);
- QCOMPARE(loc.line(), 4U);
-}
-
-/*!
- Should insert at line 4, column 1, with "protected\n" as prefix and "\n" suffix.
- */
-void tst_Codegen::protected_betwee_public_and_private()
-{
- const QByteArray src = "\n"
- "class Foo\n" // line 1
- "{\n"
- "public:\n" // line 3
- "private:\n" // line 4
- "};\n" // line 5
- "\n";
-
- Document::Ptr doc = Document::create("protected_betwee_public_and_private");
- doc->setSource(src);
- doc->parse();
- doc->check();
-
- QCOMPARE(doc->diagnosticMessages().size(), 0);
- QCOMPARE(doc->globalSymbolCount(), 1U);
-
- Class *foo = doc->globalSymbolAt(0)->asClass();
- QVERIFY(foo);
- QCOMPARE(foo->line(), 1U);
- QCOMPARE(foo->column(), 7U);
-
- Snapshot snapshot;
- snapshot.insert(doc);
- CppRefactoringChanges changes(snapshot);
- InsertionPointLocator find(changes);
- InsertionLocation loc = find.methodDeclarationInClass(
- doc->fileName(),
- foo,
- InsertionPointLocator::Protected);
- QVERIFY(loc.isValid());
- QCOMPARE(loc.prefix(), QLatin1String("protected:\n"));
- QCOMPARE(loc.suffix(), QLatin1String("\n"));
- QCOMPARE(loc.column(), 1U);
- QCOMPARE(loc.line(), 4U);
-}
-
-/*!
- Should insert at line 18, column 1, with "private slots:\n" as prefix and "\n"
- as suffix.
-
- This is the typical Qt Designer case, with test-input like what the integration
- generates.
- */
-void tst_Codegen::qtdesigner_integration()
-{
- const QByteArray src = "/**** Some long (C)opyright notice ****/\n"
- "#ifndef MAINWINDOW_H\n"
- "#define MAINWINDOW_H\n"
- "\n"
- "#include <QMainWindow>\n"
- "\n"
- "namespace Ui {\n"
- " class MainWindow;\n"
- "}\n"
- "\n"
- "class MainWindow : public QMainWindow\n" // line 10
- "{\n"
- " Q_OBJECT\n"
- "\n"
- "public:\n" // line 14
- " explicit MainWindow(QWidget *parent = 0);\n"
- " ~MainWindow();\n"
- "\n"
- "private:\n" // line 18
- " Ui::MainWindow *ui;\n"
- "};\n"
- "\n"
- "#endif // MAINWINDOW_H\n";
-
- Document::Ptr doc = Document::create("qtdesigner_integration");
- doc->setSource(src);
- doc->parse();
- doc->check();
-
- QCOMPARE(doc->diagnosticMessages().size(), 0);
- QCOMPARE(doc->globalSymbolCount(), 2U);
-
- Class *foo = doc->globalSymbolAt(1)->asClass();
- QVERIFY(foo);
- QCOMPARE(foo->line(), 10U);
- QCOMPARE(foo->column(), 7U);
-
- Snapshot snapshot;
- snapshot.insert(doc);
- CppRefactoringChanges changes(snapshot);
- InsertionPointLocator find(changes);
- InsertionLocation loc = find.methodDeclarationInClass(
- doc->fileName(),
- foo,
- InsertionPointLocator::PrivateSlot);
- QVERIFY(loc.isValid());
- QCOMPARE(loc.prefix(), QLatin1String("private slots:\n"));
- QCOMPARE(loc.suffix(), QLatin1String("\n"));
- QCOMPARE(loc.line(), 18U);
- QCOMPARE(loc.column(), 1U);
-}
-
-void tst_Codegen::definition_empty_class()
-{
- const QByteArray srcText = "\n"
- "class Foo\n" // line 1
- "{\n"
- "void foo();\n" // line 3
- "};\n"
- "\n";
-
- const QByteArray dstText = "\n"
- "int x;\n" // line 1
- "\n";
-
- Document::Ptr src = Document::create(tempPath + QLatin1String("/file.h"));
- Utils::FileSaver srcSaver(src->fileName());
- srcSaver.write(srcText);
- srcSaver.finalize();
- src->setSource(srcText);
- src->parse();
- src->check();
- QCOMPARE(src->diagnosticMessages().size(), 0);
- QCOMPARE(src->globalSymbolCount(), 1U);
-
- Document::Ptr dst = Document::create(tempPath + QLatin1String("/file.cpp"));
- Utils::FileSaver dstSaver(dst->fileName());
- dstSaver.write(dstText);
- dstSaver.finalize();
- dst->setSource(dstText);
- dst->parse();
- dst->check();
- QCOMPARE(dst->diagnosticMessages().size(), 0);
- QCOMPARE(dst->globalSymbolCount(), 1U);
-
- Snapshot snapshot;
- snapshot.insert(src);
- snapshot.insert(dst);
-
- Class *foo = src->globalSymbolAt(0)->asClass();
- QVERIFY(foo);
- QCOMPARE(foo->line(), 1U);
- QCOMPARE(foo->column(), 7U);
- QCOMPARE(foo->memberCount(), 1U);
- Declaration *decl = foo->memberAt(0)->asDeclaration();
- QVERIFY(decl);
- QCOMPARE(decl->line(), 3U);
- QCOMPARE(decl->column(), 6U);
-
- CppRefactoringChanges changes(snapshot);
- InsertionPointLocator find(changes);
- QList<InsertionLocation> locList = find.methodDefinition(decl);
- QVERIFY(locList.size() == 1);
- InsertionLocation loc = locList.first();
- QCOMPARE(loc.fileName(), dst->fileName());
- QCOMPARE(loc.prefix(), QLatin1String("\n\n"));
- QCOMPARE(loc.suffix(), QString());
- QCOMPARE(loc.line(), 1U);
- QCOMPARE(loc.column(), 7U);
-}
-
-void tst_Codegen::definition_first_member()
-{
- const QByteArray srcText = "\n"
- "class Foo\n" // line 1
- "{\n"
- "void foo();\n" // line 3
- "void bar();\n" // line 4
- "};\n"
- "\n";
-
- const QByteArray dstText = QString(
- "\n"
- "#include \"%1/file.h\"\n" // line 1
- "int x;\n"
- "\n"
- "void Foo::bar()\n" // line 4
- "{\n"
- "\n"
- "}\n"
- "\n"
- "int y;\n").arg(tempPath).toLatin1();
-
- Document::Ptr src = Document::create(tempPath + QLatin1String("/file.h"));
- Utils::FileSaver srcSaver(src->fileName());
- srcSaver.write(srcText);
- srcSaver.finalize();
- src->setSource(srcText);
- src->parse();
- src->check();
- QCOMPARE(src->diagnosticMessages().size(), 0);
- QCOMPARE(src->globalSymbolCount(), 1U);
-
- Document::Ptr dst = Document::create(tempPath + QLatin1String("/file.cpp"));
- dst->addIncludeFile(src->fileName(), 1);
- Utils::FileSaver dstSaver(dst->fileName());
- dstSaver.write(dstText);
- dstSaver.finalize();
- dst->setSource(dstText);
- dst->parse();
- dst->check();
- QCOMPARE(dst->diagnosticMessages().size(), 0);
- QCOMPARE(dst->globalSymbolCount(), 3U);
-
- Snapshot snapshot;
- snapshot.insert(src);
- snapshot.insert(dst);
-
- Class *foo = src->globalSymbolAt(0)->asClass();
- QVERIFY(foo);
- QCOMPARE(foo->line(), 1U);
- QCOMPARE(foo->column(), 7U);
- QCOMPARE(foo->memberCount(), 2U);
- Declaration *decl = foo->memberAt(0)->asDeclaration();
- QVERIFY(decl);
- QCOMPARE(decl->line(), 3U);
- QCOMPARE(decl->column(), 6U);
-
- CppRefactoringChanges changes(snapshot);
- InsertionPointLocator find(changes);
- QList<InsertionLocation> locList = find.methodDefinition(decl);
- QVERIFY(locList.size() == 1);
- InsertionLocation loc = locList.first();
- QCOMPARE(loc.fileName(), dst->fileName());
- QCOMPARE(loc.line(), 4U);
- QCOMPARE(loc.column(), 1U);
- QCOMPARE(loc.suffix(), QLatin1String("\n\n"));
- QCOMPARE(loc.prefix(), QString());
-}
-
-void tst_Codegen::definition_last_member()
-{
- const QByteArray srcText = "\n"
- "class Foo\n" // line 1
- "{\n"
- "void foo();\n" // line 3
- "void bar();\n" // line 4
- "};\n"
- "\n";
-
- const QByteArray dstText = QString(
- "\n"
- "#include \"%1/file.h\"\n" // line 1
- "int x;\n"
- "\n"
- "void Foo::foo()\n" // line 4
- "{\n"
- "\n"
- "}\n" // line 7
- "\n"
- "int y;\n").arg(tempPath).toLatin1();
-
- Document::Ptr src = Document::create(tempPath + QLatin1String("/file.h"));
- Utils::FileSaver srcSaver(src->fileName());
- srcSaver.write(srcText);
- srcSaver.finalize();
- src->setSource(srcText);
- src->parse();
- src->check();
- QCOMPARE(src->diagnosticMessages().size(), 0);
- QCOMPARE(src->globalSymbolCount(), 1U);
-
- Document::Ptr dst = Document::create(tempPath + QLatin1String("/file.cpp"));
- dst->addIncludeFile(src->fileName(), 1);
- Utils::FileSaver dstSaver(dst->fileName());
- dstSaver.write(dstText);
- dstSaver.finalize();
- dst->setSource(dstText);
- dst->parse();
- dst->check();
- QCOMPARE(dst->diagnosticMessages().size(), 0);
- QCOMPARE(dst->globalSymbolCount(), 3U);
-
- Snapshot snapshot;
- snapshot.insert(src);
- snapshot.insert(dst);
-
- Class *foo = src->globalSymbolAt(0)->asClass();
- QVERIFY(foo);
- QCOMPARE(foo->line(), 1U);
- QCOMPARE(foo->column(), 7U);
- QCOMPARE(foo->memberCount(), 2U);
- Declaration *decl = foo->memberAt(1)->asDeclaration();
- QVERIFY(decl);
- QCOMPARE(decl->line(), 4U);
- QCOMPARE(decl->column(), 6U);
-
- CppRefactoringChanges changes(snapshot);
- InsertionPointLocator find(changes);
- QList<InsertionLocation> locList = find.methodDefinition(decl);
- QVERIFY(locList.size() == 1);
- InsertionLocation loc = locList.first();
- QCOMPARE(loc.fileName(), dst->fileName());
- QCOMPARE(loc.line(), 7U);
- QCOMPARE(loc.column(), 2U);
- QCOMPARE(loc.prefix(), QLatin1String("\n\n"));
- QCOMPARE(loc.suffix(), QString());
-}
-
-void tst_Codegen::definition_middle_member()
-{
- const QByteArray srcText = "\n"
- "class Foo\n" // line 1
- "{\n"
- "void foo();\n" // line 3
- "void bar();\n" // line 4
- "void car();\n" // line 5
- "};\n"
- "\n";
-
- const QByteArray dstText = QString(
- "\n"
- "#include \"%1/file.h\"\n" // line 1
- "int x;\n"
- "\n"
- "void Foo::foo()\n" // line 4
- "{\n"
- "\n"
- "}\n" // line 7
- "\n"
- "void Foo::car()\n" // line 9
- "{\n"
- "\n"
- "}\n"
- "\n"
- "int y;\n").arg(tempPath).toLatin1();
-
- Document::Ptr src = Document::create(tempPath + QLatin1String("/file.h"));
- Utils::FileSaver srcSaver(src->fileName());
- srcSaver.write(srcText);
- srcSaver.finalize();
- src->setSource(srcText);
- src->parse();
- src->check();
- QCOMPARE(src->diagnosticMessages().size(), 0);
- QCOMPARE(src->globalSymbolCount(), 1U);
-
- Document::Ptr dst = Document::create(tempPath + QLatin1String("/file.cpp"));
- dst->addIncludeFile(src->fileName(), 1);
- Utils::FileSaver dstSaver(dst->fileName());
- dstSaver.write(dstText);
- dstSaver.finalize();
- dst->setSource(dstText);
- dst->parse();
- dst->check();
- QCOMPARE(dst->diagnosticMessages().size(), 0);
- QCOMPARE(dst->globalSymbolCount(), 4U);
-
- Snapshot snapshot;
- snapshot.insert(src);
- snapshot.insert(dst);
-
- Class *foo = src->globalSymbolAt(0)->asClass();
- QVERIFY(foo);
- QCOMPARE(foo->line(), 1U);
- QCOMPARE(foo->column(), 7U);
- QCOMPARE(foo->memberCount(), 3U);
- Declaration *decl = foo->memberAt(1)->asDeclaration();
- QVERIFY(decl);
- QCOMPARE(decl->line(), 4U);
- QCOMPARE(decl->column(), 6U);
-
- CppRefactoringChanges changes(snapshot);
- InsertionPointLocator find(changes);
- QList<InsertionLocation> locList = find.methodDefinition(decl);
- QVERIFY(locList.size() == 1);
- InsertionLocation loc = locList.first();
- QCOMPARE(loc.fileName(), dst->fileName());
- QCOMPARE(loc.line(), 7U);
- QCOMPARE(loc.column(), 2U);
- QCOMPARE(loc.prefix(), QLatin1String("\n\n"));
- QCOMPARE(loc.suffix(), QString());
-}
-
-QTEST_MAIN(tst_Codegen)
-#include "tst_codegen.moc"