From 97500f3cfe60538b9f8af85eacc6ca3ff37b801a Mon Sep 17 00:00:00 2001 From: Rochus Keller Date: Wed, 30 Jan 2019 20:26:19 +0100 Subject: [PATCH] module and symbol locator; refactoring, singleton TclEngine --- README.md | 14 ++-- VerilogCreator.json.in | 4 +- VerilogCreator.pro | 8 ++- VlCompletionAssistProvider.cpp | 106 +++++++++++++++++++++++++---- VlCompletionAssistProvider.h | 4 ++ VlModelManager.cpp | 6 ++ VlModelManager.h | 2 + VlModuleLocator.cpp | 75 +++++++++++++++++++++ VlModuleLocator.h | 42 ++++++++++++ VlPlugin.cpp | 11 +-- VlProject.cpp | 17 ----- VlProject.h | 4 -- VlSymbolLocator.cpp | 120 +++++++++++++++++++++++++++++++++ VlSymbolLocator.h | 41 +++++++++++ VlTclConfiguration.cpp | 36 ++++++++-- VlTclConfiguration.h | 5 ++ VlTclEngine.cpp | 4 +- VlTclEngine.h | 4 +- 18 files changed, 441 insertions(+), 62 deletions(-) create mode 100644 VlModuleLocator.cpp create mode 100644 VlModuleLocator.h create mode 100644 VlSymbolLocator.cpp create mode 100644 VlSymbolLocator.h diff --git a/README.md b/README.md index 5963c60..89cc876 100644 --- a/README.md +++ b/README.md @@ -12,21 +12,21 @@ The plugin is still work in progress, but it already has enough functionality to ### Implemented Features -- Syntax highlighting (including ifdefed out blocks) +- Syntax highlighting (including ifdefed out blocks and markers) - Inline code warnings and errors - Parentheses and begin/end block matching/navigation - Hover tooltips - Follow symbol under cursor, follow includes (multi-file support) -- Drop-down menu to jump to modules, module instances, functions and tasks in current file - Show where a symbol is used -- Code folding and some other features supported by QtCreator, see http://doc.qt.io/qtcreator/ +- Drop-down menu to jump to modules, module instances, functions and tasks in current file +- Outline view; see [screenshot](http://software.rochus-keller.info/vlcreator_outline_screenshot.png) +- Module locator (global) and symbol locator (current document); see [screenshot 1](http://software.rochus-keller.info/vlcreator_module_locator_screenshot.png) and [screenshot 2](http://software.rochus-keller.info/vlcreator_symbol_locator_screenshot.png) +- Syntax based code folding and some other features supported by QtCreator, see http://doc.qt.io/qtcreator/ +- Marker based code folding (MBCF); use section markers like //{ and //}, or //> and //<; see [screenshot 1](http://software.rochus-keller.info/vlcreator_mbcf_screenshot1.png) and [screenshot 2](http://software.rochus-keller.info/vlcreator_mbcf_screenshot2.png) - Project file to configure source files, include dirs, defines and libraries - Icarus Verilog build and run configuration; directly run compiler and simulator from within QtCreator - Verilator and Yosys build configurations; generate command files, optional arguments - Build configuration based on custom Tcl scripts which can access project configuration (e.g. to run Vivado commands) -- Marker based code folding (MBCF); use section markers like //{ and //}, or //> and //<; see [screenshot 1](http://software.rochus-keller.info/vlcreator_mbcf_screenshot1.png) and [screenshot 2](http://software.rochus-keller.info/vlcreator_mbcf_screenshot2.png) -- Outline view; see [screenshot 1](http://software.rochus-keller.info/vlcreator_outline_screenshot.png) - ### Project file format @@ -120,8 +120,6 @@ Since I currently consider the effort to reverse engineer each QtCreator version - Documentation - Semantic indenter (the current one simply adjusts to the previous line) - Parse output of Icarus/Verilator/Yosys and post it to the Issues pane -- Implement locator popup -- Implement outline and include panes - Implement wizzard to add or import files, generate stub modules and automatically update the vlpro file - Improve hover text - Implement options dialog (format settings, paths, etc.) diff --git a/VerilogCreator.json.in b/VerilogCreator.json.in index 71a2c77..b4161cc 100644 --- a/VerilogCreator.json.in +++ b/VerilogCreator.json.in @@ -1,7 +1,7 @@ { \"Name\" : \"VerilogCreator\", - \"Version\" : \"0.6.1\", - \"CompatVersion\" : \"0.6.1\", + \"Version\" : \"0.6.2\", + \"CompatVersion\" : \"0.6.2\", \"Vendor\" : \"Rochus Keller\", \"Copyright\" : \"(C) 2019 Rochus Keller\", \"License\" : \"GPL\", diff --git a/VerilogCreator.pro b/VerilogCreator.pro index 51ff307..ec9ae94 100644 --- a/VerilogCreator.pro +++ b/VerilogCreator.pro @@ -100,7 +100,9 @@ SOURCES += \ VlTclEngine.cpp \ VlAutoCompleter.cpp \ VlCompletionAssistProvider.cpp \ - VlOutlineWidget.cpp + VlOutlineWidget.cpp \ + VlModuleLocator.cpp \ + VlSymbolLocator.cpp HEADERS += \ verilogcreator_global.h \ @@ -126,7 +128,9 @@ HEADERS += \ VlTclEngine.h \ VlAutoCompleter.h \ VlCompletionAssistProvider.h \ - VlOutlineWidget.h + VlOutlineWidget.h \ + VlModuleLocator.h \ + VlSymbolLocator.h include (../Verilog/Verilog.pri ) diff --git a/VlCompletionAssistProvider.cpp b/VlCompletionAssistProvider.cpp index be645c1..a7112e3 100644 --- a/VlCompletionAssistProvider.cpp +++ b/VlCompletionAssistProvider.cpp @@ -18,34 +18,92 @@ */ #include "VlCompletionAssistProvider.h" +#include "VlConstants.h" #include #include #include +#include +#include +#include #include +#include +#include #include namespace Vl { + // borrowed from RubyCreator + static const QString &nameFor(const QString &s) + { + return s; + } + template + static void addProposalFromSet(QList &proposals, + const T &container, const QString &myTyping, + const QIcon &icon, int order = 0) + { + foreach (const typename T::value_type &item, container) + { + const QString &name = nameFor(item); + if (myTyping == name) + continue; + + auto proposal = new TextEditor::AssistProposalItem(); + + int indexOfParenthesis = name.indexOf(QLatin1Char('(')); + if (indexOfParenthesis != -1) { + proposal->setText(name.mid(0, indexOfParenthesis)); + proposal->setDetail(name); + } else { + proposal->setText(name); + } + + proposal->setIcon(icon); + proposal->setOrder(order); + proposals << proposal; + } + } + class CompletionAssistProcessor : public TextEditor::IAssistProcessor { public: CompletionAssistProcessor() {} ~CompletionAssistProcessor() { - qDebug() << "CompletionAssistProcessor deleted"; + //qDebug() << "CompletionAssistProcessor deleted"; } - - TextEditor::IAssistProposal* perform(const TextEditor::AssistInterface *interface) + TextEditor::IAssistProposal* perform(const TextEditor::AssistInterface *ai) { - m_interface.reset(interface); + m_interface.reset(ai); - qDebug() << "CompletionAssistProcessor::perform"; - return 0; - } - TextEditor::IAssistProposal *immediateProposal(const TextEditor::AssistInterface *) - { - qDebug() << "CompletionAssistProcessor::immediateProposal"; - return 0; + if (ai->reason() == TextEditor::IdleEditor) + return 0; + + const int startPosition = ai->position(); + + const QTextBlock block = ai->textDocument()->findBlock(startPosition); + const int linePosition = startPosition - block.position(); + const QString line = ai->textDocument()->findBlock(startPosition).text(); + + + const QString myTyping = ai->textAt(startPosition, ai->position() - startPosition); + const QString fileName = ai->fileName(); + + qDebug() << "perform" << line << myTyping; + + QList proposals; + + QStringList tmp; + tmp << "alpha" << "beta" << "gamma"; + addProposalFromSet(proposals, tmp, myTyping, QIcon(), 1); + + if( proposals.isEmpty() ) + return 0; + + TextEditor::GenericProposalModel *model = new TextEditor::GenericProposalModel(); + model->loadContent(proposals); + TextEditor::IAssistProposal *proposal = new TextEditor::GenericProposal(startPosition, model); + return proposal; } private: QScopedPointer m_interface; @@ -61,12 +119,32 @@ TextEditor::IAssistProvider::RunType CompletionAssistProvider::runType() const bool CompletionAssistProvider::supportsEditor(Core::Id editorId) const { - qDebug() << "CompletionAssistProvider::supportsEditor" << editorId; - return false; + return editorId == Constants::EditorId1; } TextEditor::IAssistProcessor*CompletionAssistProvider::createProcessor() const { - qDebug() << "CompletionAssistProvider::createProcessor"; return new CompletionAssistProcessor(); } + +bool CompletionAssistProvider::isActivationCharSequence(const QString& sequence) const +{ + if( sequence.size() < SeqLen ) + return false; + const QChar cur = sequence[SeqLen-1]; + const QChar before1 = sequence[SeqLen-2]; + const QChar before2 = sequence[SeqLen-3]; + //qDebug() << "isActivationCharSequence" << before2 << before1 << ch; + if( cur == '.' || cur == '(' || cur == '`' ) + return true; + if( false ) // cur.isLetter() || cur == '$' || cur == '_' || cur == '`' ) + return true; + else + return false; +} + +bool CompletionAssistProvider::isContinuationChar(const QChar& c) const +{ + //qDebug() << "isContinuationChar" << c; + return c.isLetterOrNumber() || c == '_' || c == '$'; +} diff --git a/VlCompletionAssistProvider.h b/VlCompletionAssistProvider.h index d925832..3071b2b 100644 --- a/VlCompletionAssistProvider.h +++ b/VlCompletionAssistProvider.h @@ -29,11 +29,15 @@ namespace Vl { Q_OBJECT public: + enum { SeqLen = 3 }; // overrides RunType runType() const; bool supportsEditor(Core::Id editorId) const; TextEditor::IAssistProcessor* createProcessor() const; + int activationCharSequenceLength() const { return SeqLen; } + bool isActivationCharSequence(const QString &sequence) const; + bool isContinuationChar(const QChar &c) const; }; } diff --git a/VlModelManager.cpp b/VlModelManager.cpp index f8375fe..0cee928 100644 --- a/VlModelManager.cpp +++ b/VlModelManager.cpp @@ -53,6 +53,7 @@ CrossRefModel*ModelManager::getModelForFile(const QString& fileName) { m = new CrossRefModel(this,d_fcache); connect( m, SIGNAL(sigModelUpdated()), this, SLOT(onModelUpdated()) ); + d_paths[m] = fileName; } d_lastUsed = m; return m; @@ -95,6 +96,11 @@ CrossRefModel*ModelManager::getModelForCurrentProjectOrDirPath(const QString& di return mdl; } +QString ModelManager::getPathOf(CrossRefModel* m) const +{ + return d_paths.value(m); +} + ModelManager*ModelManager::instance() { if( d_inst ) diff --git a/VlModelManager.h b/VlModelManager.h index 7ca0962..4a2ae71 100644 --- a/VlModelManager.h +++ b/VlModelManager.h @@ -39,6 +39,7 @@ namespace Vl CrossRefModel* getModelForCurrentProject(); CrossRefModel* getModelForCurrentProjectOrDirPath(const QString& dirPath , bool initIfEmpty = false); CrossRefModel* getLastUsed() const { return d_lastUsed; } + QString getPathOf(CrossRefModel*) const; FileCache* getFileCache() const { return d_fcache; } @@ -50,6 +51,7 @@ namespace Vl private: static ModelManager* d_inst; QHash d_models; // Project File -> Code Model + QHash d_paths; CrossRefModel* d_lastUsed; FileCache* d_fcache; }; diff --git a/VlModuleLocator.cpp b/VlModuleLocator.cpp new file mode 100644 index 0000000..92a9928 --- /dev/null +++ b/VlModuleLocator.cpp @@ -0,0 +1,75 @@ +/* +* Copyright 2019 Rochus Keller +* +* This file is part of the VerilogCreator plugin. +* +* The following is the license that applies to this copy of the +* plugin. For a license to use the plugin under conditions +* other than those described here, please email to me@rochus-keller.ch. +* +* GNU General Public License Usage +* This file may be used under the terms of the GNU General Public +* License (GPL) versions 2.0 or 3.0 as published by the Free Software +* Foundation and appearing in the file LICENSE.GPL included in +* the packaging of this file. Please review the following information +* to ensure GNU General Public Licensing requirements will be met: +* http://www.fsf.org/licensing/licenses/info/GPLv2.html and +* http://www.gnu.org/copyleft/gpl.html. +*/ + +#include "VlModuleLocator.h" +#include "VlModelManager.h" +#include +#include +using namespace Vl; + +ModuleLocator::ModuleLocator() +{ + setId("Modules"); + setDisplayName(tr("Verilog modules and UDPs in global namespace")); + setShortcutString(QString(QLatin1Char('m'))); + setIncludedByDefault(false); +} + +QList ModuleLocator::matchesFor(QFutureInterface& future, + const QString& entry) +{ + Q_UNUSED(future); + + QList res; + + CrossRefModel* mdl = ModelManager::instance()->getModelForCurrentProject(); + if( mdl == 0 ) + return res; + + QDir path( ModelManager::instance()->getPathOf(mdl) ); + + CrossRefModel::IdentDeclRefList l = mdl->getGlobalNames(); + + QStringMatcher matcher(entry, Qt::CaseInsensitive); // ByteArrayMatcher is case sensitive instead + + QPixmap icon(":/verilogcreator/images/block.png"); + foreach(const CrossRefModel::IdentDeclRef& id, l ) + { + const QString name = QString::fromLatin1(id->tok().d_val); + if( matcher.indexIn( name ) != -1 ) + { + res << Core::LocatorFilterEntry( this, name, QVariant::fromValue(CrossRefModel::SymRef(id)),icon); + res.last().extraInfo = path.relativeFilePath( id->tok().d_sourcePath ); + } + } + return res; +} + +void ModuleLocator::accept(Core::LocatorFilterEntry selection) const +{ + CrossRefModel::SymRef sym = selection.internalData.value(); + Core::EditorManager::openEditorAt( sym->tok().d_sourcePath, + sym->tok().d_lineNr - 1, sym->tok().d_colNr + 0 ); +} + +void ModuleLocator::refresh(QFutureInterface& future) +{ + Q_UNUSED(future); +} + diff --git a/VlModuleLocator.h b/VlModuleLocator.h new file mode 100644 index 0000000..3f8e9b3 --- /dev/null +++ b/VlModuleLocator.h @@ -0,0 +1,42 @@ +#ifndef VLMODULELOCATOR_H +#define VLMODULELOCATOR_H + +/* +* Copyright 2019 Rochus Keller +* +* This file is part of the VerilogCreator plugin. +* +* The following is the license that applies to this copy of the +* plugin. For a license to use the plugin under conditions +* other than those described here, please email to me@rochus-keller.ch. +* +* GNU General Public License Usage +* This file may be used under the terms of the GNU General Public +* License (GPL) versions 2.0 or 3.0 as published by the Free Software +* Foundation and appearing in the file LICENSE.GPL included in +* the packaging of this file. Please review the following information +* to ensure GNU General Public Licensing requirements will be met: +* http://www.fsf.org/licensing/licenses/info/GPLv2.html and +* http://www.gnu.org/copyleft/gpl.html. +*/ + +#include + +namespace Vl +{ + class ModuleLocator : public Core::ILocatorFilter + { + Q_OBJECT + public: + explicit ModuleLocator(); + + // overrides + QList matchesFor(QFutureInterface &future, + const QString &entry); + void accept(Core::LocatorFilterEntry selection) const; + void refresh(QFutureInterface &future); + + }; +} + +#endif // VLMODULELOCATOR_H diff --git a/VlPlugin.cpp b/VlPlugin.cpp index c07db85..fbea34b 100644 --- a/VlPlugin.cpp +++ b/VlPlugin.cpp @@ -26,6 +26,9 @@ #include "VlConfigurationFactory.h" #include "VlProject.h" #include "VlOutlineWidget.h" +#include "VlModuleLocator.h" +#include "VlCompletionAssistProvider.h" +#include "VlSymbolLocator.h" #include #include #include @@ -38,9 +41,6 @@ #include #include #include -#if VL_QTC_VER >= 0405 -#include -#endif #include #include @@ -88,7 +88,8 @@ bool VerilogCreatorPlugin::initialize(const QStringList &arguments, QString *err addAutoReleasedObject(new Vl::EditorFactory1); addAutoReleasedObject(new Vl::EditorFactory2); addAutoReleasedObject(new Vl::OutlineWidgetFactory); - //TODO addAutoReleasedObject(new SymbolFilter([](const QString &file) {.. + addAutoReleasedObject(new Vl::ModuleLocator); + addAutoReleasedObject(new Vl::SymbolLocator); addAutoReleasedObject(new Vl::ProjectManager); addAutoReleasedObject(new Vl::MakeStepFactory); addAutoReleasedObject(new Vl::BuildConfigurationFactory); @@ -100,7 +101,7 @@ bool VerilogCreatorPlugin::initialize(const QStringList &arguments, QString *err //addAutoReleasedObject(new ProjectWizard); - //addAutoReleasedObject(new CompletionAssistProvider); + //addAutoReleasedObject(new Vl::CompletionAssistProvider); Core::Context context(Vl::Constants::EditorId1); Core::ActionContainer *contextMenu1 = Core::ActionManager::createMenu(Vl::Constants::EditorContextMenuId1); diff --git a/VlProject.cpp b/VlProject.cpp index a1f3014..6c36b41 100644 --- a/VlProject.cpp +++ b/VlProject.cpp @@ -78,8 +78,6 @@ Project::Project(ProjectManager* projectManager, const QString& fileName): loadProject(fileName); d_watcher.addPath(fileName); connect( &d_watcher, SIGNAL(fileChanged(QString)), this, SLOT(onFileChanged(QString)) ); - d_tcl = new TclEngine(this); - d_tcl->setGetVar(tclGetVar,this); } QStringList Project::getConfig(const QString& key) const @@ -402,21 +400,6 @@ void Project::fillNode(const QStringList& files, ProjectExplorer::FolderNode* ro } } -QStringList Project::tclGetVar(const QByteArray& name, void* data) -{ - //qDebug() << "tclGetVar called" << name; - const QByteArray lower = name.toLower(); - Project* p = static_cast(data); - if( lower == "srcfiles" ) - return p->getSrcFiles(); - else if( lower == "libfiles" ) - return p->getLibFiles(); - else if( lower == "incdirs" ) - return p->getIncDirs(); - else - return p->getConfig( name ); -} - #if VL_QTC_VER >= 0306 ProjectExplorer::Project::RestoreResult Project::fromMap(const QVariantMap &map, QString *errorMessage) #else diff --git a/VlProject.h b/VlProject.h index ecc6a01..c5b025a 100644 --- a/VlProject.h +++ b/VlProject.h @@ -23,7 +23,6 @@ #include #include -#include "VlTclEngine.h" namespace TextEditor { class TextDocument; } namespace ProjectExplorer { class FolderNode; } @@ -46,7 +45,6 @@ namespace Vl QStringList getConfig( const QString& key ) const; QStringList getIncDirs() const; QString getTopMod() const; - TclEngine* getTcl() const { return d_tcl; } void reload(); // overrides @@ -61,7 +59,6 @@ namespace Vl static void findFilesInDirs( const QStringList& dirs, const QStringList& filter, QSet& files ); static void findFilesInDir(const QString& dir, const QStringList& filter, QStringList& files , bool recursive); static void fillNode( const QStringList& files, ProjectExplorer::FolderNode* ); - static QStringList tclGetVar(const QByteArray& name, void* data); #if VL_QTC_VER >= 0306 RestoreResult fromMap(const QVariantMap &map, QString *errorMessage) Q_DECL_OVERRIDE; @@ -78,7 +75,6 @@ namespace Vl QStringList d_srcFiles, d_libFiles, d_incDirs; QMap d_config; QFileSystemWatcher d_watcher; - TclEngine* d_tcl; }; } diff --git a/VlSymbolLocator.cpp b/VlSymbolLocator.cpp new file mode 100644 index 0000000..f654259 --- /dev/null +++ b/VlSymbolLocator.cpp @@ -0,0 +1,120 @@ +/* +* Copyright 2019 Rochus Keller +* +* This file is part of the VerilogCreator plugin. +* +* The following is the license that applies to this copy of the +* plugin. For a license to use the plugin under conditions +* other than those described here, please email to me@rochus-keller.ch. +* +* GNU General Public License Usage +* This file may be used under the terms of the GNU General Public +* License (GPL) versions 2.0 or 3.0 as published by the Free Software +* Foundation and appearing in the file LICENSE.GPL included in +* the packaging of this file. Please review the following information +* to ensure GNU General Public Licensing requirements will be met: +* http://www.fsf.org/licensing/licenses/info/GPLv2.html and +* http://www.gnu.org/copyleft/gpl.html. +*/ + +#include "VlSymbolLocator.h" +#include "VlModelManager.h" +#include +#include +using namespace Vl; + +SymbolLocator::SymbolLocator() +{ + setId("Symbols"); + setDisplayName(tr("Verilog symbols in current document")); + setShortcutString(QString(QLatin1Char('.'))); + setIncludedByDefault(false); +} + +static bool lessThan(const Core::LocatorFilterEntry&s1, const Core::LocatorFilterEntry&s2) +{ + return s1.displayName.compare( s2.displayName, Qt::CaseInsensitive ) < 0 || + ( !(s2.displayName.compare( s1.displayName, Qt::CaseInsensitive ) < 0) + && s1.extraInfo.compare( s2.extraInfo, Qt::CaseInsensitive ) < 0 ); +} + +QList SymbolLocator::matchesFor(QFutureInterface& future, const QString& entry) +{ + Q_UNUSED(future); + + QList res; + + CrossRefModel* mdl = ModelManager::instance()->getModelForCurrentProject(); + if( mdl == 0 ) + return res; + + const QString fileName = Core::EditorManager::instance()->currentDocument() ? + Core::EditorManager::instance()->currentDocument()->filePath().toString() : QString(); + if( fileName.isEmpty() ) + return res; + + CrossRefModel::IdentDeclRefList l = mdl->getGlobalNames(); + + QStringMatcher matcher(entry, Qt::CaseInsensitive); // ByteArrayMatcher is case sensitive instead + + QPixmap iMod(":/verilogcreator/images/block.png"); + QPixmap iVar(":/verilogcreator/images/var.png"); + QPixmap iFunc(":/verilogcreator/images/func.png"); + + foreach(const CrossRefModel::IdentDeclRef& id, l ) + { + if( id->tok().d_sourcePath != fileName ) + continue; + + const QString name = QString::fromLatin1(id->tok().d_val); + if( matcher.indexIn( name ) != -1 ) + { + res << Core::LocatorFilterEntry( this, name, QVariant::fromValue(CrossRefModel::SymRef(id)),iMod); + res.back().extraInfo = QString("(%1)").arg( SynTree::rToStr( id->decl()->tok().d_type ) ); + } + const CrossRefModel::Scope* s = id->decl()->toScope(); + if( s ) + { + foreach( const CrossRefModel::IdentDeclRef& id2, s->getNames() ) + { + const QString name2 = QString::fromLatin1(id2->tok().d_val); + if( matcher.indexIn( name2 ) != -1 ) + { + const int type = id2->decl()->tok().d_type; + QPixmap icon; + switch(type) + { + case SynTree::R_task_declaration: + case SynTree::R_function_declaration: + icon = iFunc; + break; + default: + icon = iVar; + break; + } + res << Core::LocatorFilterEntry( this, name2, QVariant::fromValue(CrossRefModel::SymRef(id2)), icon ); +// res << Core::LocatorFilterEntry( this, QString("%1.%2").arg(name).arg(name2), +// QVariant::fromValue(CrossRefModel::SymRef(id2)), icon ); + res.back().extraInfo = QString("%1 (%2)").arg(name).arg( SynTree::rToStr( type ) ); + //res.back().extraInfo = QString("(%1)").arg( SynTree::rToStr( type ) ); + } + } + } + + } + std::sort( res.begin(), res.end(), lessThan ); + return res; +} + +void SymbolLocator::accept(Core::LocatorFilterEntry selection) const +{ + CrossRefModel::SymRef sym = selection.internalData.value(); + Core::EditorManager::openEditorAt( sym->tok().d_sourcePath, + sym->tok().d_lineNr - 1, sym->tok().d_colNr + 0 ); +} + +void SymbolLocator::refresh(QFutureInterface& future) +{ + Q_UNUSED(future); +} + diff --git a/VlSymbolLocator.h b/VlSymbolLocator.h new file mode 100644 index 0000000..ac46c83 --- /dev/null +++ b/VlSymbolLocator.h @@ -0,0 +1,41 @@ +#ifndef VLSYMBOLLOCATOR_H +#define VLSYMBOLLOCATOR_H + +/* +* Copyright 2019 Rochus Keller +* +* This file is part of the VerilogCreator plugin. +* +* The following is the license that applies to this copy of the +* plugin. For a license to use the plugin under conditions +* other than those described here, please email to me@rochus-keller.ch. +* +* GNU General Public License Usage +* This file may be used under the terms of the GNU General Public +* License (GPL) versions 2.0 or 3.0 as published by the Free Software +* Foundation and appearing in the file LICENSE.GPL included in +* the packaging of this file. Please review the following information +* to ensure GNU General Public Licensing requirements will be met: +* http://www.fsf.org/licensing/licenses/info/GPLv2.html and +* http://www.gnu.org/copyleft/gpl.html. +*/ + +#include + +namespace Vl +{ + class SymbolLocator : public Core::ILocatorFilter + { + Q_OBJECT + public: + SymbolLocator(); + + // overrides + QList matchesFor(QFutureInterface &future, + const QString &entry); + void accept(Core::LocatorFilterEntry selection) const; + void refresh(QFutureInterface &future); + }; +} + +#endif // VLSYMBOLLOCATOR_H diff --git a/VlTclConfiguration.cpp b/VlTclConfiguration.cpp index 605d1ca..61eb373 100644 --- a/VlTclConfiguration.cpp +++ b/VlTclConfiguration.cpp @@ -134,9 +134,16 @@ void TclBuildConfigWidget::environmentChanged() } TclStep::TclStep(ProjectExplorer::BuildStepList* parent): - AbstractProcessStep(parent, ID) + AbstractProcessStep(parent, ID),d_tcl(0) { setDefaultDisplayName(tr("Tcl") ); + d_tcl = TclEngine::addRef(); +} + +TclStep::~TclStep() +{ + if( d_tcl ) + TclEngine::release(); } bool TclStep::init() @@ -158,7 +165,7 @@ bool TclStep::init() Vl::Project* p = dynamic_cast( project() ); Q_ASSERT( p != 0 ); - if( !p->getTcl()->isReady() ) + if( !d_tcl->isReady() ) { emit addTask(ProjectExplorer::Task(ProjectExplorer::Task::Error, tr( "The Tcl interpreter is not ready."), @@ -213,17 +220,19 @@ void TclStep::run(QFutureInterface& fi) processStarted(); Vl::Project* p = dynamic_cast( project() ); - p->getTcl()->setWriteLog(writeLog,this); + d_tcl->setWriteLog(writeLog,this); + d_tcl->setGetVar(tclGetVar,p); int res = 0; - if( !p->getTcl()->runFile( d_scriptFile ) ) + if( !d_tcl->runFile( d_scriptFile ) ) res = -1; - p->getTcl()->setWriteLog(0,0); + d_tcl->setWriteLog(0,0); + d_tcl->setGetVar(0,0); // AbstractProcessStep::run(fi); // startet einen Prozess; wir machen das hier selber // processFinished( res, QProcess::NormalExit ); // uses m_process - QString str = p->getTcl()->getResult().trimmed(); + QString str = d_tcl->getResult().trimmed(); if( !str.isEmpty() ) str = " : " + str; emit addOutput(tr("The script \"%1\" exited with code %2%3").arg(d_scriptFile).arg(res).arg(str), @@ -266,6 +275,21 @@ void TclStep::writeLog(const QByteArray& msg, bool err, void* data) p->stdOutput(QString::fromUtf8(msg)); } +QStringList TclStep::tclGetVar(const QByteArray& name, void* data) +{ + //qDebug() << "tclGetVar called" << name; + const QByteArray lower = name.toLower(); + Project* p = static_cast(data); + if( lower == "srcfiles" ) + return p->getSrcFiles(); + else if( lower == "libfiles" ) + return p->getLibFiles(); + else if( lower == "incdirs" ) + return p->getIncDirs(); + else + return p->getConfig( name ); +} + QString TclStep::makeCommand(const Utils::Environment& ) const { return d_scriptFile; diff --git a/VlTclConfiguration.h b/VlTclConfiguration.h index ffdb94b..daca2e6 100644 --- a/VlTclConfiguration.h +++ b/VlTclConfiguration.h @@ -67,6 +67,8 @@ namespace Vl TclBuildConfig* d_conf; }; + class TclEngine; + class TclStep : public ProjectExplorer::AbstractProcessStep { Q_OBJECT @@ -74,6 +76,7 @@ namespace Vl static const char* ID; explicit TclStep(ProjectExplorer::BuildStepList *parent); + ~TclStep(); bool init(); void run(QFutureInterface &fi); @@ -84,8 +87,10 @@ namespace Vl QString makeCommand(const Utils::Environment &environment) const; bool fromMap(const QVariantMap &map); static void writeLog(const QByteArray& msg, bool err, void* data); + static QStringList tclGetVar(const QByteArray& name, void* data); private: QString d_scriptFile; + TclEngine* d_tcl; friend class TclMakeStepWidget; }; diff --git a/VlTclEngine.cpp b/VlTclEngine.cpp index 3bffc58..aac90f1 100644 --- a/VlTclEngine.cpp +++ b/VlTclEngine.cpp @@ -272,7 +272,7 @@ TclEngine*TclEngine::addRef() { if( s_refCount <= 0 ) { - //qDebug() << "TCL create"; + qDebug() << "TCL create"; s_refCount = 0; s_inst = new TclEngine(); } @@ -285,7 +285,7 @@ void TclEngine::release() s_refCount--; if( s_refCount == 0 ) { - //qDebug() << "TCL delete"; + qDebug() << "TCL delete"; delete s_inst; s_inst = 0; } diff --git a/VlTclEngine.h b/VlTclEngine.h index 8ecd760..7cee0af 100644 --- a/VlTclEngine.h +++ b/VlTclEngine.h @@ -39,10 +39,10 @@ namespace Vl bool runFile( const QString& ); QString getResult() const; - struct Imp; - protected: static TclEngine* addRef(); static void release(); + + struct Imp; private: Imp* d_imp; };