diff options
author | Friedemann Kleint <[email protected]> | 2011-03-31 10:57:33 +0200 |
---|---|---|
committer | Friedemann Kleint <[email protected]> | 2011-03-31 10:57:33 +0200 |
commit | 4ed14a1f2c80e6831e0cfc80982b771cbb25cef8 (patch) | |
tree | 9b2ed7afe9708daeb564b2ef10dbe1e839fe0145 /src/plugins | |
parent | 938dd71e1aec0dba20e50076960fea49de77f804 (diff) |
VCS[perforce,svn,vcs]: Use convenience to tag editors for reuse.
Introduce convenience to determine editor tags to avoid
crashes on empty files arguments, etc (VCSBaseEditor).
Add diff-whitespace handling and 'Revert chunk' to Perforce.
Task-number: QTCREATORBUG-4305
Diffstat (limited to 'src/plugins')
-rw-r--r-- | src/plugins/cvs/cvsplugin.cpp | 43 | ||||
-rw-r--r-- | src/plugins/perforce/perforceplugin.cpp | 98 | ||||
-rw-r--r-- | src/plugins/perforce/perforceplugin.h | 3 | ||||
-rw-r--r-- | src/plugins/subversion/subversionplugin.cpp | 49 | ||||
-rw-r--r-- | src/plugins/vcsbase/vcsbaseeditor.cpp | 43 | ||||
-rw-r--r-- | src/plugins/vcsbase/vcsbaseeditor.h | 8 |
6 files changed, 165 insertions, 79 deletions
diff --git a/src/plugins/cvs/cvsplugin.cpp b/src/plugins/cvs/cvsplugin.cpp index 26b4c520267..30dd956d2b4 100644 --- a/src/plugins/cvs/cvsplugin.cpp +++ b/src/plugins/cvs/cvsplugin.cpp @@ -155,14 +155,6 @@ static inline QString debugCodec(const QTextCodec *c) return c ? QString::fromAscii(c->name()) : QString::fromAscii("Null codec"); } -Core::IEditor* locateEditor(const char *property, const QString &entry) -{ - foreach (Core::IEditor *ed, Core::EditorManager::instance()->openedEditors()) - if (ed->property(property).toString() == entry) - return ed; - return 0; -} - static inline bool messageBoxQuestion(const QString &title, const QString &question, QWidget *parent = 0) { return QMessageBox::question(parent, title, question, QMessageBox::Yes|QMessageBox::No) == QMessageBox::Yes; @@ -535,12 +527,9 @@ static inline void setDiffBaseDirectory(Core::IEditor *editor, const QString &db // with a diff editor and re-run the diff with parameters. struct CvsDiffParameters { - CvsDiffParameters() : reUseEditor(false) {} - QString workingDir; QStringList arguments; QStringList files; - bool reUseEditor; }; // Parameter widget controlling whitespace diff mode, associated with a parameter @@ -574,7 +563,6 @@ CvsDiffParameterWidget::CvsDiffParameterWidget(const CvsDiffParameters &p, QWidg void CvsDiffParameterWidget::triggerReRun() { CvsDiffParameters effectiveParameters = m_parameters; - effectiveParameters.reUseEditor = true; effectiveParameters.arguments = arguments(); emit reRunDiff(effectiveParameters); } @@ -617,18 +605,17 @@ void CVSPlugin::cvsDiff(const CvsDiffParameters &p) output = tr("The files do not differ."); // diff of a single file? re-use an existing view if possible to support // the common usage pattern of continuously changing and diffing a file - if (p.files.count() == 1 || p.reUseEditor) { - // Show in the same editor if diff has been executed before - if (Core::IEditor *editor = locateEditor("originalFileName", id)) { - editor->createNew(output); - Core::EditorManager::instance()->activateEditor(editor, Core::EditorManager::ModeSwitch); - setDiffBaseDirectory(editor, p.workingDir); - return; - } + // Show in the same editor if diff has been executed before + const QString tag = VCSBase::VCSBaseEditorWidget::editorTag(VCSBase::DiffOutput, p.workingDir, p.files); + if (Core::IEditor *existingEditor = VCSBase::VCSBaseEditorWidget::locateEditorByTag(tag)) { + existingEditor->createNew(output); + Core::EditorManager::instance()->activateEditor(existingEditor, Core::EditorManager::ModeSwitch); + setDiffBaseDirectory(existingEditor, p.workingDir); + return; } const QString title = QString::fromLatin1("cvs diff %1").arg(id); Core::IEditor *editor = showOutputInEditor(title, output, VCSBase::DiffOutput, source, codec); - editor->setProperty("originalFileName", id); + VCSBase::VCSBaseEditorWidget::tagEditor(editor, tag); setDiffBaseDirectory(editor, p.workingDir); CVSEditor *diffEditorWidget = qobject_cast<CVSEditor*>(editor->widget()); QTC_ASSERT(diffEditorWidget, return ; ) @@ -893,13 +880,14 @@ void CVSPlugin::filelog(const QString &workingDir, // Re-use an existing view if possible to support // the common usage pattern of continuously changing and diffing a file - if (Core::IEditor *editor = locateEditor("logFileName", id)) { + const QString tag = VCSBase::VCSBaseEditorWidget::editorTag(VCSBase::LogOutput, workingDir, files); + if (Core::IEditor *editor = VCSBase::VCSBaseEditorWidget::locateEditorByTag(tag)) { editor->createNew(response.stdOut); Core::EditorManager::instance()->activateEditor(editor, Core::EditorManager::ModeSwitch); } else { const QString title = QString::fromLatin1("cvs log %1").arg(id); Core::IEditor *newEditor = showOutputInEditor(title, response.stdOut, VCSBase::LogOutput, source, codec); - newEditor->setProperty("logFileName", id); + VCSBase::VCSBaseEditorWidget::tagEditor(newEditor, tag); if (enableAnnotationContextMenu) VCSBase::VCSBaseEditorWidget::getVcsBaseEditor(newEditor)->setFileLogAnnotateEnabled(true); } @@ -1034,14 +1022,15 @@ void CVSPlugin::annotate(const QString &workingDir, const QString &file, if (lineNumber < 1) lineNumber = VCSBase::VCSBaseEditorWidget::lineNumberOfCurrentEditor(file); - if (Core::IEditor *editor = locateEditor("annotateFileName", id)) { + const QString tag = VCSBase::VCSBaseEditorWidget::editorTag(VCSBase::AnnotateOutput, workingDir, QStringList(file), revision); + if (Core::IEditor *editor = VCSBase::VCSBaseEditorWidget::locateEditorByTag(tag)) { editor->createNew(response.stdOut); VCSBase::VCSBaseEditorWidget::gotoLineOfEditor(editor, lineNumber); Core::EditorManager::instance()->activateEditor(editor, Core::EditorManager::ModeSwitch); } else { const QString title = QString::fromLatin1("cvs annotate %1").arg(id); Core::IEditor *newEditor = showOutputInEditor(title, response.stdOut, VCSBase::AnnotateOutput, source, codec); - newEditor->setProperty("annotateFileName", id); + VCSBase::VCSBaseEditorWidget::tagEditor(newEditor, tag); VCSBase::VCSBaseEditorWidget::gotoLineOfEditor(newEditor, lineNumber); } } @@ -1230,14 +1219,14 @@ bool CVSPlugin::describe(const QString &repositoryPath, // Re-use an existing view if possible to support // the common usage pattern of continuously changing and diffing a file const QString commitId = entries.front().revisions.front().commitId; - if (Core::IEditor *editor = locateEditor("describeChange", commitId)) { + if (Core::IEditor *editor = VCSBase::VCSBaseEditorWidget::locateEditorByTag(commitId)) { editor->createNew(output); Core::EditorManager::instance()->activateEditor(editor, Core::EditorManager::ModeSwitch); setDiffBaseDirectory(editor, repositoryPath); } else { const QString title = QString::fromLatin1("cvs describe %1").arg(commitId); Core::IEditor *newEditor = showOutputInEditor(title, output, VCSBase::DiffOutput, entries.front().file, codec); - newEditor->setProperty("describeChange", commitId); + VCSBase::VCSBaseEditorWidget::tagEditor(newEditor, commitId); setDiffBaseDirectory(newEditor, repositoryPath); } return true; diff --git a/src/plugins/perforce/perforceplugin.cpp b/src/plugins/perforce/perforceplugin.cpp index 24e83723f99..0f412356873 100644 --- a/src/plugins/perforce/perforceplugin.cpp +++ b/src/plugins/perforce/perforceplugin.cpp @@ -60,6 +60,7 @@ #include <vcsbase/basevcssubmiteditorfactory.h> #include <vcsbase/vcsbaseeditor.h> #include <vcsbase/vcsbaseoutputwindow.h> +#include <vcsbase/vcsbaseeditorparameterwidget.h> #include <QtCore/QtPlugin> #include <QtCore/QDebug> @@ -1213,32 +1214,74 @@ void PerforcePlugin::slotSubmitDiff(const QStringList &files) p4Diff(m_commitWorkingDirectory, files); } -void PerforcePlugin::p4Diff(const QString &workingDir, const QStringList &files) +struct PerforceDiffParameters { - Core::IEditor *existingEditor = 0; + QString workingDir; + QStringList diffArguments; + QStringList files; +}; - QTextCodec *codec = VCSBase::VCSBaseEditorWidget::getCodec(workingDir, files); - const QString id = VCSBase::VCSBaseEditorWidget::getTitleId(workingDir, files); - const QString source = VCSBase::VCSBaseEditorWidget::getSource(workingDir, files); +// Parameter widget controlling whitespace diff mode, associated with a parameter +class PerforceDiffParameterWidget : public VCSBase::VCSBaseEditorParameterWidget +{ + Q_OBJECT +public: + explicit PerforceDiffParameterWidget(const PerforceDiffParameters &p, QWidget *parent = 0); + +signals: + void reRunDiff(const Perforce::Internal::PerforceDiffParameters &); + +private slots: + void triggerReRun(); + +private: + const PerforceDiffParameters m_parameters; +}; + +PerforceDiffParameterWidget::PerforceDiffParameterWidget(const PerforceDiffParameters &p, QWidget *parent) : + VCSBase::VCSBaseEditorParameterWidget(parent), m_parameters(p) +{ + setBaseArguments(p.diffArguments); + addIgnoreWhiteSpaceButton(QString(QLatin1Char('w'))); + connect(this, SIGNAL(argumentsChanged()), this, SLOT(triggerReRun())); +} + +void PerforceDiffParameterWidget::triggerReRun() +{ + PerforceDiffParameters effectiveParameters = m_parameters; + effectiveParameters.diffArguments = arguments(); + emit reRunDiff(effectiveParameters); +} +void PerforcePlugin::p4Diff(const QString &workingDir, const QStringList &files) +{ + PerforceDiffParameters p; + p.workingDir = workingDir; + p.files = files; + p.diffArguments.push_back(QString(QLatin1Char('u'))); + p4Diff(p); +} + +void PerforcePlugin::p4Diff(const PerforceDiffParameters &p) +{ + QTextCodec *codec = VCSBase::VCSBaseEditorWidget::getCodec(p.workingDir, p.files); + const QString id = VCSBase::VCSBaseEditorWidget::getTitleId(p.workingDir, p.files); // Reuse existing editors for that id - foreach (Core::IEditor *ed, Core::EditorManager::instance()->openedEditors()) { - if (ed->file()->property("originalFileName").toString() == id) { - existingEditor = ed; - break; - } - } + const QString tag = VCSBase::VCSBaseEditorWidget::editorTag(VCSBase::DiffOutput, p.workingDir, p.files); + Core::IEditor *existingEditor = VCSBase::VCSBaseEditorWidget::locateEditorByTag(tag); // Split arguments according to size QStringList args; - args << QLatin1String("diff") << QLatin1String("-du"); + args << QLatin1String("diff"); + if (!p.diffArguments.isEmpty()) // -duw.. + args << (QLatin1String("-d") + p.diffArguments.join(QString())); QStringList extraArgs; - if (files.size() > 1) { - extraArgs = files; + if (p.files.size() > 1) { + extraArgs = p.files; } else { - args.append(files); + args.append(p.files); } const unsigned flags = CommandToWindow|StdErrToWindow|ErrorToWindow|OverrideDiffEnvironment; - const PerforceResponse result = runP4Cmd(workingDir, args, flags, + const PerforceResponse result = runP4Cmd(p.workingDir, args, flags, extraArgs, QByteArray(), codec); if (result.error) return; @@ -1246,12 +1289,23 @@ void PerforcePlugin::p4Diff(const QString &workingDir, const QStringList &files) if (existingEditor) { existingEditor->createNew(result.stdOut); Core::EditorManager::instance()->activateEditor(existingEditor, Core::EditorManager::ModeSwitch); - } else { - Core::IEditor *editor = showOutputInEditor(tr("p4 diff %1").arg(id), result.stdOut, VCSBase::DiffOutput, - VCSBase::VCSBaseEditorWidget::getSource(workingDir, files), - codec); - editor->file()->setProperty("originalFileName", id); + return; } + // Create new editor + Core::IEditor *editor = showOutputInEditor(tr("p4 diff %1").arg(id), result.stdOut, VCSBase::DiffOutput, + VCSBase::VCSBaseEditorWidget::getSource(p.workingDir, p.files), + codec); + VCSBase::VCSBaseEditorWidget::tagEditor(editor, tag); + VCSBase::VCSBaseEditorWidget *diffEditorWidget = qobject_cast<VCSBase::VCSBaseEditorWidget *>(editor->widget()); + // Wire up the parameter widget to trigger a re-run on + // parameter change and 'revert' from inside the diff editor. + diffEditorWidget->setRevertDiffChunkEnabled(true); + PerforceDiffParameterWidget *pw = new PerforceDiffParameterWidget(p); + connect(pw, SIGNAL(reRunDiff(Perforce::Internal::PerforceDiffParameters)), + this, SLOT(p4Diff(Perforce::Internal::PerforceDiffParameters))); + connect(diffEditorWidget, SIGNAL(diffChunkReverted(VCSBase::DiffChunk)), + pw, SLOT(triggerReRun())); + diffEditorWidget->setConfigurationWidget(pw); } void PerforcePlugin::describe(const QString & source, const QString &n) @@ -1498,3 +1552,5 @@ void PerforcePlugin::getTopLevel() } Q_EXPORT_PLUGIN(Perforce::Internal::PerforcePlugin) + +#include "perforceplugin.moc" diff --git a/src/plugins/perforce/perforceplugin.h b/src/plugins/perforce/perforceplugin.h index e7558c04b23..23186bd3884 100644 --- a/src/plugins/perforce/perforceplugin.h +++ b/src/plugins/perforce/perforceplugin.h @@ -63,7 +63,7 @@ namespace Locator { namespace Perforce { namespace Internal { - +struct PerforceDiffParameters; class PerforceVersionControl; struct PerforceResponse @@ -111,6 +111,7 @@ public: public slots: void describe(const QString &source, const QString &n); void vcsAnnotate(const QString &file, const QString &revision /* = QString() */, int lineNumber); + void p4Diff(const Perforce::Internal::PerforceDiffParameters &p); private slots: void openCurrentFile(); diff --git a/src/plugins/subversion/subversionplugin.cpp b/src/plugins/subversion/subversionplugin.cpp index 4b2b1503d78..97e3a9099db 100644 --- a/src/plugins/subversion/subversionplugin.cpp +++ b/src/plugins/subversion/subversionplugin.cpp @@ -153,14 +153,6 @@ static inline QString debugCodec(const QTextCodec *c) return c ? QString::fromAscii(c->name()) : QString::fromAscii("Null codec"); } -Core::IEditor* locateEditor(const char *property, const QString &entry) -{ - foreach (Core::IEditor *ed, Core::EditorManager::instance()->openedEditors()) - if (ed->property(property).toString() == entry) - return ed; - return 0; -} - // Parse "svn status" output for added/modified/deleted files // "M<7blanks>file" typedef QList<SubversionSubmitEditor::StatusFilePair> StatusList; @@ -540,13 +532,10 @@ void SubversionPlugin::diffCommitFiles(const QStringList &files) // with a diff editor and re-run the diff with parameters. struct SubversionDiffParameters { - SubversionDiffParameters() : reUseEditor(false) {} - QString workingDir; QStringList arguments; QStringList files; QString diffName; - bool reUseEditor; }; // Parameter widget controlling whitespace diff mode, associated with a parameter @@ -577,7 +566,6 @@ SubversionDiffParameterWidget::SubversionDiffParameterWidget(const SubversionDif void SubversionDiffParameterWidget::triggerReRun() { SubversionDiffParameters effectiveParameters = m_parameters; - effectiveParameters.reUseEditor = true; // Subversion wants" -x -<ext-args>", default being -u const QStringList a = arguments(); if (!a.isEmpty()) @@ -621,20 +609,18 @@ void SubversionPlugin::svnDiff(const Subversion::Internal::SubversionDiffParamet // diff of a single file? re-use an existing view if possible to support // the common usage pattern of continuously changing and diffing a file - if (p.files.count() == 1 || p.reUseEditor) { - // Show in the same editor if diff has been executed before - if (Core::IEditor *editor = locateEditor("originalFileName", p.files.front())) { - editor->createNew(response.stdOut); - Core::EditorManager::instance()->activateEditor(editor, Core::EditorManager::ModeSwitch); - setDiffBaseDirectory(editor, p.workingDir); - return; - } + const QString tag = VCSBase::VCSBaseEditorWidget::editorTag(VCSBase::DiffOutput, p.workingDir, p.files); + // Show in the same editor if diff has been executed before + if (Core::IEditor *existingEditor = VCSBase::VCSBaseEditorWidget::locateEditorByTag(tag)) { + existingEditor->createNew(response.stdOut); + Core::EditorManager::instance()->activateEditor(existingEditor, Core::EditorManager::ModeSwitch); + setDiffBaseDirectory(existingEditor, p.workingDir); + return; } const QString title = QString::fromLatin1("svn diff %1").arg(diffName); Core::IEditor *editor = showOutputInEditor(title, response.stdOut, VCSBase::DiffOutput, source, codec); setDiffBaseDirectory(editor, p.workingDir); - if (p.files.count() == 1) - editor->setProperty("originalFileName", p.files.front()); + VCSBase::VCSBaseEditorWidget::tagEditor(editor, tag); SubversionEditor *diffEditorWidget = qobject_cast<SubversionEditor *>(editor->widget()); QTC_ASSERT(diffEditorWidget, return ; ) @@ -938,14 +924,15 @@ void SubversionPlugin::filelog(const QString &workingDir, // the common usage pattern of continuously changing and diffing a file const QString id = VCSBase::VCSBaseEditorWidget::getTitleId(workingDir, files); - if (Core::IEditor *editor = locateEditor("logFileName", id)) { + const QString tag = VCSBase::VCSBaseEditorWidget::editorTag(VCSBase::LogOutput, workingDir, files); + if (Core::IEditor *editor = VCSBase::VCSBaseEditorWidget::locateEditorByTag(tag)) { editor->createNew(response.stdOut); Core::EditorManager::instance()->activateEditor(editor, Core::EditorManager::ModeSwitch); } else { const QString title = QString::fromLatin1("svn log %1").arg(id); const QString source = VCSBase::VCSBaseEditorWidget::getSource(workingDir, files); Core::IEditor *newEditor = showOutputInEditor(title, response.stdOut, VCSBase::LogOutput, source, /*codec*/0); - newEditor->setProperty("logFileName", id); + VCSBase::VCSBaseEditorWidget::tagEditor(newEditor, tag); if (enableAnnotationContextMenu) VCSBase::VCSBaseEditorWidget::getVcsBaseEditor(newEditor)->setFileLogAnnotateEnabled(true); } @@ -1012,16 +999,17 @@ void SubversionPlugin::vcsAnnotate(const QString &workingDir, const QString &fil if (lineNumber <= 0) lineNumber = VCSBase::VCSBaseEditorWidget::lineNumberOfCurrentEditor(source); // Determine id - const QString id = VCSBase::VCSBaseEditorWidget::getTitleId(workingDir, QStringList(file), revision); - - if (Core::IEditor *editor = locateEditor("annotateFileName", id)) { + const QStringList files = QStringList(file); + const QString id = VCSBase::VCSBaseEditorWidget::getTitleId(workingDir, files, revision); + const QString tag = VCSBase::VCSBaseEditorWidget::editorTag(VCSBase::AnnotateOutput, workingDir, files); + if (Core::IEditor *editor = VCSBase::VCSBaseEditorWidget::locateEditorByTag(tag)) { editor->createNew(response.stdOut); VCSBase::VCSBaseEditorWidget::gotoLineOfEditor(editor, lineNumber); Core::EditorManager::instance()->activateEditor(editor, Core::EditorManager::ModeSwitch); } else { const QString title = QString::fromLatin1("svn annotate %1").arg(id); Core::IEditor *newEditor = showOutputInEditor(title, response.stdOut, VCSBase::AnnotateOutput, source, codec); - newEditor->setProperty("annotateFileName", id); + VCSBase::VCSBaseEditorWidget::tagEditor(newEditor, tag); VCSBase::VCSBaseEditorWidget::gotoLineOfEditor(newEditor, lineNumber); } } @@ -1079,13 +1067,14 @@ void SubversionPlugin::describe(const QString &source, const QString &changeNr) // Re-use an existing view if possible to support // the common usage pattern of continuously changing and diffing a file const QString id = diffArg + source; - if (Core::IEditor *editor = locateEditor("describeChange", id)) { + const QString tag = VCSBase::VCSBaseEditorWidget::editorTag(VCSBase::DiffOutput, source, QStringList(), changeNr); + if (Core::IEditor *editor = VCSBase::VCSBaseEditorWidget::locateEditorByTag(tag)) { editor->createNew(description); Core::EditorManager::instance()->activateEditor(editor, Core::EditorManager::ModeSwitch); } else { const QString title = QString::fromLatin1("svn describe %1#%2").arg(fi.fileName(), changeNr); Core::IEditor *newEditor = showOutputInEditor(title, description, VCSBase::DiffOutput, source, codec); - newEditor->setProperty("describeChange", id); + VCSBase::VCSBaseEditorWidget::tagEditor(newEditor, tag); } } diff --git a/src/plugins/vcsbase/vcsbaseeditor.cpp b/src/plugins/vcsbase/vcsbaseeditor.cpp index b8a97fa72ec..add1da01cfb 100644 --- a/src/plugins/vcsbase/vcsbaseeditor.cpp +++ b/src/plugins/vcsbase/vcsbaseeditor.cpp @@ -1068,6 +1068,49 @@ void VCSBaseEditorWidget::slotRevertDiffChunk() emit diffChunkReverted(chunk); } +// Tagging of editors for re-use. +QString VCSBaseEditorWidget::editorTag(EditorContentType t, + const QString &workingDirectory, + const QStringList &files, + const QString &revision) +{ + const QChar colon = QLatin1Char(':'); + QString rc = QString::number(t); + rc += colon; + if (!revision.isEmpty()) { + rc += revision; + rc += colon; + } + rc += workingDirectory; + if (!files.isEmpty()) { + rc += colon; + rc += files.join(QString(colon)); + } + return rc; +} + +static const char tagPropertyC[] = "_q_VCSBaseEditorTag"; + +void VCSBaseEditorWidget::tagEditor(Core::IEditor *e, const QString &tag) +{ + e->setProperty(tagPropertyC, QVariant(tag)); +} + +Core::IEditor* VCSBaseEditorWidget::locateEditorByTag(const QString &tag) +{ + Core::IEditor *rc = 0; + foreach (Core::IEditor *ed, Core::EditorManager::instance()->openedEditors()) { + const QVariant tagPropertyValue = ed->property(tagPropertyC); + if (tagPropertyValue.type() == QVariant::String && tagPropertyValue.toString() == tag) { + rc = ed; + break; + } + } + if (VCSBase::Constants::Internal::debug) + qDebug() << "locateEditorByTag " << tag << rc; + return rc; +} + } // namespace VCSBase #include "vcsbaseeditor.moc" diff --git a/src/plugins/vcsbase/vcsbaseeditor.h b/src/plugins/vcsbase/vcsbaseeditor.h index 607512b7d0d..d5df5338b34 100644 --- a/src/plugins/vcsbase/vcsbaseeditor.h +++ b/src/plugins/vcsbase/vcsbaseeditor.h @@ -186,6 +186,14 @@ public: bool setConfigurationWidget(QWidget *w); QWidget *configurationWidget() const; + /* Tagging editors: Sometimes, an editor should be re-used, for example, when showing + * a diff of the same file with different diff-options. In order to be able to find + * the editor, they get a 'tag' containing type and parameters (dynamic property string). */ + static void tagEditor(Core::IEditor *e, const QString &tag); + static Core::IEditor* locateEditorByTag(const QString &tag); + static QString editorTag(EditorContentType t, const QString &workingDirectory, const QStringList &files, + const QString &revision = QString()); + signals: // These signals also exist in the opaque editable (IEditor) that is // handled by the editor manager for convenience. They are emitted |