├── examples ├── hello.vlpro ├── counter.vlpro ├── hello.v ├── Readme.txt ├── counter.v └── counter_tb.v ├── images ├── var.png ├── block.png ├── class.png ├── func.png └── category.png ├── VerilogCreator.qrc ├── VerilogCreator.json.in ├── VlEditor.mimetypes.xml ├── verilogcreator_global.h ├── VlHoverHandler.h ├── VlProjectManager.h ├── VlIndenter.h ├── VlSymbolLocator.h ├── VlModuleLocator.h ├── VlProjectManager.cpp ├── VlHighlighter.h ├── VlTclEngine.h ├── VlCompletionAssistProvider.h ├── VlAutoCompleter.h ├── VlModelManager.h ├── VlConstants.h ├── VlPlugin.h ├── VlSdfEditor.h ├── VlOutlineWidget.h ├── VlIndenter.cpp ├── VlProjectEditor.h ├── VlModuleLocator.cpp ├── VlProject.h ├── VlVerilogEditor.h ├── VlAutoCompleter.cpp ├── VlOutlineMdl.h ├── VlConfigurationFactory.h ├── VlOutlineWidget.cpp ├── VlYosysConfiguration.h ├── VerilogCreator.pro ├── VlVerilatorConfiguration.h ├── VlSymbolLocator.cpp ├── VlTclConfiguration.h ├── VlModelManager.cpp ├── VlHoverHandler.cpp ├── VlIcarusConfiguration.h ├── VlProjectEditor.cpp ├── VlSdfEditor.cpp ├── VlPlugin.cpp ├── VlHighlighter.cpp ├── VlProject.cpp ├── VlCompletionAssistProvider.cpp ├── VlTclEngine.cpp ├── VlConfigurationFactory.cpp ├── README.md └── VlOutlineMdl.cpp /examples/hello.vlpro: -------------------------------------------------------------------------------- 1 | 2 | SRCFILES += hello.v 3 | 4 | -------------------------------------------------------------------------------- /examples/counter.vlpro: -------------------------------------------------------------------------------- 1 | 2 | 3 | SRCFILES += counter.v counter_tb.v 4 | -------------------------------------------------------------------------------- /images/var.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rochus-keller/VerilogCreator/HEAD/images/var.png -------------------------------------------------------------------------------- /images/block.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rochus-keller/VerilogCreator/HEAD/images/block.png -------------------------------------------------------------------------------- /images/class.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rochus-keller/VerilogCreator/HEAD/images/class.png -------------------------------------------------------------------------------- /images/func.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rochus-keller/VerilogCreator/HEAD/images/func.png -------------------------------------------------------------------------------- /images/category.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rochus-keller/VerilogCreator/HEAD/images/category.png -------------------------------------------------------------------------------- /examples/hello.v: -------------------------------------------------------------------------------- 1 | module hello; 2 | initial 3 | begin 4 | $display("Hello, World"); 5 | $finish ; 6 | end 7 | endmodule 8 | -------------------------------------------------------------------------------- /examples/Readme.txt: -------------------------------------------------------------------------------- 1 | These are some examples from the Icarus Verilog users guide. 2 | See https://iverilog.fandom.com/wiki/Getting_Started 3 | You can just open and run the vlpro files and see the result 4 | in the Application Output pane in case there is a proper 5 | installation of Icarus Verilog available on your machine. 6 | -------------------------------------------------------------------------------- /examples/counter.v: -------------------------------------------------------------------------------- 1 | module counter(out, clk, reset); 2 | 3 | parameter WIDTH = 8; 4 | 5 | output [WIDTH-1 : 0] out; 6 | input clk, reset; 7 | 8 | reg [WIDTH-1 : 0] out; 9 | wire clk, reset; 10 | 11 | always @(posedge clk or posedge reset) 12 | if (reset) 13 | out <= 0; 14 | else 15 | out <= out + 1; 16 | 17 | endmodule // counter 18 | -------------------------------------------------------------------------------- /VerilogCreator.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | VlEditor.mimetypes.xml 4 | 5 | 6 | images/class.png 7 | images/func.png 8 | images/var.png 9 | images/block.png 10 | images/category.png 11 | 12 | 13 | -------------------------------------------------------------------------------- /VerilogCreator.json.in: -------------------------------------------------------------------------------- 1 | { 2 | \"Name\" : \"VerilogCreator\", 3 | \"Version\" : \"0.8.0\", 4 | \"CompatVersion\" : \"0.8.0\", 5 | \"Vendor\" : \"Rochus Keller\", 6 | \"Copyright\" : \"(C) 2019 Rochus Keller\", 7 | \"License\" : \"GPL\", 8 | \"Category\" : \"Other Languages\", 9 | \"Description\" : \"QtCreator based IDE for Verilog\", 10 | \"Url\" : \"https://github.com/rochus-keller/VerilogCreator\", 11 | $$dependencyList 12 | } 13 | 14 | -------------------------------------------------------------------------------- /examples/counter_tb.v: -------------------------------------------------------------------------------- 1 | module test; 2 | 3 | /* Make a reset that pulses once. */ 4 | reg reset = 0; 5 | initial begin 6 | # 17 reset = 1; 7 | # 11 reset = 0; 8 | # 29 reset = 1; 9 | # 11 reset = 0; 10 | # 100 $stop; 11 | end 12 | 13 | /* Make a regular pulsing clock. */ 14 | reg clk = 0; 15 | always #5 clk = !clk; 16 | 17 | wire [7:0] value; 18 | counter c1 (value, clk, reset); 19 | 20 | initial 21 | $monitor("At time %t, value = %h (%0d)", 22 | $time, value, value); 23 | endmodule // test 24 | -------------------------------------------------------------------------------- /VlEditor.mimetypes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Verilog project file 6 | 7 | 8 | 9 | 10 | Verilog source file 11 | 12 | 13 | 14 | 15 | 16 | 17 | Sdf file 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /verilogcreator_global.h: -------------------------------------------------------------------------------- 1 | #ifndef VERILOGCREATOR_GLOBAL_H 2 | #define VERILOGCREATOR_GLOBAL_H 3 | 4 | /* 5 | * Copyright 2018 Rochus Keller 6 | * 7 | * This file is part of the VerilogCreator plugin. 8 | * 9 | * The following is the license that applies to this copy of the 10 | * plugin. For a license to use the plugin under conditions 11 | * other than those described here, please email to me@rochus-keller.ch. 12 | * 13 | * GNU General Public License Usage 14 | * This file may be used under the terms of the GNU General Public 15 | * License (GPL) versions 2.0 or 3.0 as published by the Free Software 16 | * Foundation and appearing in the file LICENSE.GPL included in 17 | * the packaging of this file. Please review the following information 18 | * to ensure GNU General Public Licensing requirements will be met: 19 | * http://www.fsf.org/licensing/licenses/info/GPLv2.html and 20 | * http://www.gnu.org/copyleft/gpl.html. 21 | */ 22 | 23 | #include 24 | 25 | #if defined(VERILOGCREATOR_LIBRARY) 26 | # define VERILOGCREATORSHARED_EXPORT Q_DECL_EXPORT 27 | #else 28 | # define VERILOGCREATORSHARED_EXPORT Q_DECL_IMPORT 29 | #endif 30 | 31 | #endif // VERILOGCREATOR_GLOBAL_H 32 | 33 | -------------------------------------------------------------------------------- /VlHoverHandler.h: -------------------------------------------------------------------------------- 1 | #ifndef VLHOVERHANDLER_H 2 | #define VLHOVERHANDLER_H 3 | 4 | /* 5 | * Copyright 2018 Rochus Keller 6 | * 7 | * This file is part of the VerilogCreator plugin. 8 | * 9 | * The following is the license that applies to this copy of the 10 | * plugin. For a license to use the plugin under conditions 11 | * other than those described here, please email to me@rochus-keller.ch. 12 | * 13 | * GNU General Public License Usage 14 | * This file may be used under the terms of the GNU General Public 15 | * License (GPL) versions 2.0 or 3.0 as published by the Free Software 16 | * Foundation and appearing in the file LICENSE.GPL included in 17 | * the packaging of this file. Please review the following information 18 | * to ensure GNU General Public Licensing requirements will be met: 19 | * http://www.fsf.org/licensing/licenses/info/GPLv2.html and 20 | * http://www.gnu.org/copyleft/gpl.html. 21 | */ 22 | 23 | #include 24 | 25 | namespace Vl 26 | { 27 | class VerilogHoverHandler : public TextEditor::BaseHoverHandler 28 | { 29 | public: 30 | VerilogHoverHandler(); 31 | void identifyMatch(TextEditor::TextEditorWidget *editorWidget, int pos); 32 | }; 33 | } 34 | 35 | #endif // VLHOVERHANDLER_H 36 | -------------------------------------------------------------------------------- /VlProjectManager.h: -------------------------------------------------------------------------------- 1 | #ifndef VLPROJECTMANAGER_H 2 | #define VLPROJECTMANAGER_H 3 | 4 | /* 5 | * Copyright 2018 Rochus Keller 6 | * 7 | * This file is part of the VerilogCreator plugin. 8 | * 9 | * The following is the license that applies to this copy of the 10 | * plugin. For a license to use the plugin under conditions 11 | * other than those described here, please email to me@rochus-keller.ch. 12 | * 13 | * GNU General Public License Usage 14 | * This file may be used under the terms of the GNU General Public 15 | * License (GPL) versions 2.0 or 3.0 as published by the Free Software 16 | * Foundation and appearing in the file LICENSE.GPL included in 17 | * the packaging of this file. Please review the following information 18 | * to ensure GNU General Public Licensing requirements will be met: 19 | * http://www.fsf.org/licensing/licenses/info/GPLv2.html and 20 | * http://www.gnu.org/copyleft/gpl.html. 21 | */ 22 | 23 | #if VL_QTC_VER < 0405 24 | #include 25 | 26 | namespace Vl 27 | { 28 | class ProjectManager : public ProjectExplorer::IProjectManager 29 | { 30 | Q_OBJECT 31 | public: 32 | explicit ProjectManager(); 33 | 34 | virtual QString mimeType() const; 35 | virtual ProjectExplorer::Project *openProject(const QString &fileName, QString *errorString); 36 | 37 | }; 38 | } 39 | #endif 40 | #endif // VLPROJECTMANAGER_H 41 | -------------------------------------------------------------------------------- /VlIndenter.h: -------------------------------------------------------------------------------- 1 | #ifndef VLINDENTER_H 2 | #define VLINDENTER_H 3 | 4 | /* 5 | * Copyright 2018 Rochus Keller 6 | * 7 | * This file is part of the VerilogCreator plugin. 8 | * 9 | * The following is the license that applies to this copy of the 10 | * plugin. For a license to use the plugin under conditions 11 | * other than those described here, please email to me@rochus-keller.ch. 12 | * 13 | * GNU General Public License Usage 14 | * This file may be used under the terms of the GNU General Public 15 | * License (GPL) versions 2.0 or 3.0 as published by the Free Software 16 | * Foundation and appearing in the file LICENSE.GPL included in 17 | * the packaging of this file. Please review the following information 18 | * to ensure GNU General Public Licensing requirements will be met: 19 | * http://www.fsf.org/licensing/licenses/info/GPLv2.html and 20 | * http://www.gnu.org/copyleft/gpl.html. 21 | */ 22 | 23 | #include 24 | 25 | namespace Vl 26 | { 27 | class VerilogIndenter : public TextEditor::Indenter 28 | { 29 | public: 30 | VerilogIndenter(); 31 | 32 | // overrides 33 | bool isElectricCharacter(const QChar &ch) const; 34 | void indentBlock(QTextDocument *document, 35 | const QTextBlock &block, 36 | const QChar &typedChar, 37 | const TextEditor::TabSettings &settings); 38 | }; 39 | } 40 | 41 | #endif // VLINDENTER_H 42 | -------------------------------------------------------------------------------- /VlSymbolLocator.h: -------------------------------------------------------------------------------- 1 | #ifndef VLSYMBOLLOCATOR_H 2 | #define VLSYMBOLLOCATOR_H 3 | 4 | /* 5 | * Copyright 2019 Rochus Keller 6 | * 7 | * This file is part of the VerilogCreator plugin. 8 | * 9 | * The following is the license that applies to this copy of the 10 | * plugin. For a license to use the plugin under conditions 11 | * other than those described here, please email to me@rochus-keller.ch. 12 | * 13 | * GNU General Public License Usage 14 | * This file may be used under the terms of the GNU General Public 15 | * License (GPL) versions 2.0 or 3.0 as published by the Free Software 16 | * Foundation and appearing in the file LICENSE.GPL included in 17 | * the packaging of this file. Please review the following information 18 | * to ensure GNU General Public Licensing requirements will be met: 19 | * http://www.fsf.org/licensing/licenses/info/GPLv2.html and 20 | * http://www.gnu.org/copyleft/gpl.html. 21 | */ 22 | 23 | #include 24 | 25 | namespace Vl 26 | { 27 | class SymbolLocator : public Core::ILocatorFilter 28 | { 29 | Q_OBJECT 30 | public: 31 | SymbolLocator(); 32 | 33 | // overrides 34 | QList matchesFor(QFutureInterface &future, 35 | const QString &entry); 36 | void accept(Core::LocatorFilterEntry selection) const; 37 | void refresh(QFutureInterface &future); 38 | }; 39 | } 40 | 41 | #endif // VLSYMBOLLOCATOR_H 42 | -------------------------------------------------------------------------------- /VlModuleLocator.h: -------------------------------------------------------------------------------- 1 | #ifndef VLMODULELOCATOR_H 2 | #define VLMODULELOCATOR_H 3 | 4 | /* 5 | * Copyright 2019 Rochus Keller 6 | * 7 | * This file is part of the VerilogCreator plugin. 8 | * 9 | * The following is the license that applies to this copy of the 10 | * plugin. For a license to use the plugin under conditions 11 | * other than those described here, please email to me@rochus-keller.ch. 12 | * 13 | * GNU General Public License Usage 14 | * This file may be used under the terms of the GNU General Public 15 | * License (GPL) versions 2.0 or 3.0 as published by the Free Software 16 | * Foundation and appearing in the file LICENSE.GPL included in 17 | * the packaging of this file. Please review the following information 18 | * to ensure GNU General Public Licensing requirements will be met: 19 | * http://www.fsf.org/licensing/licenses/info/GPLv2.html and 20 | * http://www.gnu.org/copyleft/gpl.html. 21 | */ 22 | 23 | #include 24 | 25 | namespace Vl 26 | { 27 | class ModuleLocator : public Core::ILocatorFilter 28 | { 29 | Q_OBJECT 30 | public: 31 | explicit ModuleLocator(); 32 | 33 | // overrides 34 | QList matchesFor(QFutureInterface &future, 35 | const QString &entry); 36 | void accept(Core::LocatorFilterEntry selection) const; 37 | void refresh(QFutureInterface &future); 38 | 39 | }; 40 | } 41 | 42 | #endif // VLMODULELOCATOR_H 43 | -------------------------------------------------------------------------------- /VlProjectManager.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Rochus Keller 3 | * 4 | * This file is part of the VerilogCreator plugin. 5 | * 6 | * The following is the license that applies to this copy of the 7 | * plugin. For a license to use the plugin under conditions 8 | * other than those described here, please email to me@rochus-keller.ch. 9 | * 10 | * GNU General Public License Usage 11 | * This file may be used under the terms of the GNU General Public 12 | * License (GPL) versions 2.0 or 3.0 as published by the Free Software 13 | * Foundation and appearing in the file LICENSE.GPL included in 14 | * the packaging of this file. Please review the following information 15 | * to ensure GNU General Public Licensing requirements will be met: 16 | * http://www.fsf.org/licensing/licenses/info/GPLv2.html and 17 | * http://www.gnu.org/copyleft/gpl.html. 18 | */ 19 | 20 | #include "VlProjectManager.h" 21 | #include "VlConstants.h" 22 | #include "VlProject.h" 23 | #include 24 | using namespace Vl; 25 | 26 | #if VL_QTC_VER < 0405 27 | ProjectManager::ProjectManager() 28 | { 29 | 30 | } 31 | 32 | QString Vl::ProjectManager::mimeType() const 33 | { 34 | return QLatin1String(Constants::ProjectMimeType); 35 | } 36 | 37 | ProjectExplorer::Project*Vl::ProjectManager::openProject(const QString& fileName, QString* errorString) 38 | { 39 | if (!QFileInfo(fileName).isFile()) { 40 | *errorString = tr("Failed opening project '%1': Project is not a file").arg(fileName); 41 | return 0; 42 | } 43 | 44 | return new Project(this, fileName); 45 | } 46 | #endif 47 | -------------------------------------------------------------------------------- /VlHighlighter.h: -------------------------------------------------------------------------------- 1 | #ifndef VLHIGHLIGHTER_H 2 | #define VLHIGHLIGHTER_H 3 | 4 | /* 5 | * Copyright 2018 Rochus Keller 6 | * 7 | * This file is part of the VerilogCreator plugin. 8 | * 9 | * The following is the license that applies to this copy of the 10 | * plugin. For a license to use the plugin under conditions 11 | * other than those described here, please email to me@rochus-keller.ch. 12 | * 13 | * GNU General Public License Usage 14 | * This file may be used under the terms of the GNU General Public 15 | * License (GPL) versions 2.0 or 3.0 as published by the Free Software 16 | * Foundation and appearing in the file LICENSE.GPL included in 17 | * the packaging of this file. Please review the following information 18 | * to ensure GNU General Public Licensing requirements will be met: 19 | * http://www.fsf.org/licensing/licenses/info/GPLv2.html and 20 | * http://www.gnu.org/copyleft/gpl.html. 21 | */ 22 | 23 | #include 24 | #include 25 | 26 | namespace Vl 27 | { 28 | class VerilogHighlighter : public TextEditor::SyntaxHighlighter 29 | { 30 | public: 31 | enum { TokenProp = QTextFormat::UserProperty }; 32 | explicit VerilogHighlighter(QTextDocument *parent = 0); 33 | 34 | protected: 35 | QTextCharFormat formatForCategory(int) const; 36 | 37 | // overrides 38 | void highlightBlock(const QString &text); 39 | 40 | private: 41 | enum Category { C_Num, C_Str, C_Kw, C_Type, C_Ident, C_Op, C_Pp, C_Cmt, C_Section, C_Brack, C_Max }; 42 | QTextCharFormat d_format[C_Max]; 43 | }; 44 | 45 | } 46 | 47 | #endif // VLHIGHLIGHTER_H 48 | -------------------------------------------------------------------------------- /VlTclEngine.h: -------------------------------------------------------------------------------- 1 | #ifndef VLTCLENGINE_H 2 | #define VLTCLENGINE_H 3 | 4 | /* 5 | * Copyright 2018 Rochus Keller 6 | * 7 | * This file is part of the VerilogCreator plugin. 8 | * 9 | * The following is the license that applies to this copy of the 10 | * plugin. For a license to use the plugin under conditions 11 | * other than those described here, please email to me@rochus-keller.ch. 12 | * 13 | * GNU General Public License Usage 14 | * This file may be used under the terms of the GNU General Public 15 | * License (GPL) versions 2.0 or 3.0 as published by the Free Software 16 | * Foundation and appearing in the file LICENSE.GPL included in 17 | * the packaging of this file. Please review the following information 18 | * to ensure GNU General Public Licensing requirements will be met: 19 | * http://www.fsf.org/licensing/licenses/info/GPLv2.html and 20 | * http://www.gnu.org/copyleft/gpl.html. 21 | */ 22 | 23 | #include 24 | 25 | namespace Vl 26 | { 27 | class TclEngine : public QObject 28 | { 29 | public: 30 | typedef QStringList (*GetVar)( const QByteArray& name, void* data ); 31 | typedef void (*WriteLog)( const QByteArray& msg, bool err, void* data ); 32 | 33 | explicit TclEngine(QObject *parent = 0); 34 | ~TclEngine(); 35 | 36 | bool isReady() const; 37 | void setGetVar( GetVar, void* data ); 38 | void setWriteLog( WriteLog, void* data ); 39 | bool runFile( const QString& ); 40 | QString getResult() const; 41 | 42 | static TclEngine* addRef(); 43 | static void release(); 44 | 45 | struct Imp; 46 | private: 47 | Imp* d_imp; 48 | }; 49 | } 50 | 51 | #endif // VLTCLENGINE_H 52 | -------------------------------------------------------------------------------- /VlCompletionAssistProvider.h: -------------------------------------------------------------------------------- 1 | #ifndef VLCOMPLETIONASSISTPROVIDER_H 2 | #define VLCOMPLETIONASSISTPROVIDER_H 3 | 4 | /* 5 | * Copyright 2019 Rochus Keller 6 | * 7 | * This file is part of the VerilogCreator plugin. 8 | * 9 | * The following is the license that applies to this copy of the 10 | * plugin. For a license to use the plugin under conditions 11 | * other than those described here, please email to me@rochus-keller.ch. 12 | * 13 | * GNU General Public License Usage 14 | * This file may be used under the terms of the GNU General Public 15 | * License (GPL) versions 2.0 or 3.0 as published by the Free Software 16 | * Foundation and appearing in the file LICENSE.GPL included in 17 | * the packaging of this file. Please review the following information 18 | * to ensure GNU General Public Licensing requirements will be met: 19 | * http://www.fsf.org/licensing/licenses/info/GPLv2.html and 20 | * http://www.gnu.org/copyleft/gpl.html. 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | namespace Vl 28 | { 29 | class CompletionAssistProvider : public TextEditor::CompletionAssistProvider 30 | { 31 | Q_OBJECT 32 | public: 33 | enum { SeqLen = 4 }; 34 | 35 | static int checkSequence(const QString& , int minLen = 1 ); 36 | 37 | // overrides 38 | RunType runType() const; 39 | bool supportsEditor(Core::Id editorId) const; 40 | TextEditor::IAssistProcessor* createProcessor() const; 41 | int activationCharSequenceLength() const { return SeqLen; } 42 | bool isActivationCharSequence(const QString &sequence) const; 43 | bool isContinuationChar(const QChar &c) const; 44 | }; 45 | } 46 | 47 | #endif // VLCOMPLETIONASSISTPROVIDER_H 48 | -------------------------------------------------------------------------------- /VlAutoCompleter.h: -------------------------------------------------------------------------------- 1 | #ifndef VLAUTOCOMPLETER_H 2 | #define VLAUTOCOMPLETER_H 3 | 4 | /* 5 | * Copyright 2019 Rochus Keller 6 | * 7 | * This file is part of the VerilogCreator plugin. 8 | * 9 | * The following is the license that applies to this copy of the 10 | * plugin. For a license to use the plugin under conditions 11 | * other than those described here, please email to me@rochus-keller.ch. 12 | * 13 | * GNU General Public License Usage 14 | * This file may be used under the terms of the GNU General Public 15 | * License (GPL) versions 2.0 or 3.0 as published by the Free Software 16 | * Foundation and appearing in the file LICENSE.GPL included in 17 | * the packaging of this file. Please review the following information 18 | * to ensure GNU General Public Licensing requirements will be met: 19 | * http://www.fsf.org/licensing/licenses/info/GPLv2.html and 20 | * http://www.gnu.org/copyleft/gpl.html. 21 | */ 22 | 23 | #include 24 | 25 | namespace Vl 26 | { 27 | class AutoCompleter : public TextEditor::AutoCompleter 28 | { 29 | public: 30 | AutoCompleter() {} 31 | 32 | virtual bool contextAllowsAutoParentheses(const QTextCursor &cursor, 33 | const QString &textToInsert = QString()) const; 34 | virtual bool contextAllowsElectricCharacters(const QTextCursor &cursor) const; 35 | virtual bool isInComment(const QTextCursor &cursor) const; 36 | virtual bool isInString(const QTextCursor &cursor) const; 37 | virtual QString insertMatchingBrace(const QTextCursor &cursor, 38 | const QString &text, 39 | QChar la, 40 | int *skippedChars) const; 41 | virtual QString insertParagraphSeparator(const QTextCursor &cursor) const; 42 | }; 43 | 44 | } 45 | 46 | #endif // VLAUTOCOMPLETER_H 47 | -------------------------------------------------------------------------------- /VlModelManager.h: -------------------------------------------------------------------------------- 1 | #ifndef VLMODELMANAGER_H 2 | #define VLMODELMANAGER_H 3 | 4 | /* 5 | * Copyright 2018 Rochus Keller 6 | * 7 | * This file is part of the VerilogCreator plugin. 8 | * 9 | * The following is the license that applies to this copy of the 10 | * plugin. For a license to use the plugin under conditions 11 | * other than those described here, please email to me@rochus-keller.ch. 12 | * 13 | * GNU General Public License Usage 14 | * This file may be used under the terms of the GNU General Public 15 | * License (GPL) versions 2.0 or 3.0 as published by the Free Software 16 | * Foundation and appearing in the file LICENSE.GPL included in 17 | * the packaging of this file. Please review the following information 18 | * to ensure GNU General Public Licensing requirements will be met: 19 | * http://www.fsf.org/licensing/licenses/info/GPLv2.html and 20 | * http://www.gnu.org/copyleft/gpl.html. 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | namespace Vl 29 | { 30 | class ModelManager : public QObject 31 | { 32 | Q_OBJECT 33 | public: 34 | explicit ModelManager(QObject *parent = 0); 35 | ~ModelManager(); 36 | 37 | CrossRefModel* getModelForFile(const QString& fileName ); 38 | CrossRefModel* getModelForDir(const QString& dirPath , bool initIfEmpty = false); 39 | CrossRefModel* getModelForCurrentProject(); 40 | CrossRefModel* getModelForCurrentProjectOrDirPath(const QString& dirPath , bool initIfEmpty = false); 41 | CrossRefModel* getLastUsed() const { return d_lastUsed; } 42 | QString getPathOf(CrossRefModel*) const; 43 | 44 | FileCache* getFileCache() const { return d_fcache; } 45 | 46 | static ModelManager* instance(); 47 | 48 | protected slots: 49 | void onModelUpdated(); 50 | 51 | private: 52 | static ModelManager* d_inst; 53 | QHash d_models; // Project File -> Code Model 54 | QHash d_paths; 55 | CrossRefModel* d_lastUsed; 56 | FileCache* d_fcache; 57 | }; 58 | } 59 | 60 | #endif // VLMODELMANAGER_H 61 | -------------------------------------------------------------------------------- /VlConstants.h: -------------------------------------------------------------------------------- 1 | #ifndef VLCONSTANTS_H 2 | #define VLCONSTANTS_H 3 | 4 | /* 5 | * Copyright 2018 Rochus Keller 6 | * 7 | * This file is part of the VerilogCreator plugin. 8 | * 9 | * The following is the license that applies to this copy of the 10 | * plugin. For a license to use the plugin under conditions 11 | * other than those described here, please email to me@rochus-keller.ch. 12 | * 13 | * GNU General Public License Usage 14 | * This file may be used under the terms of the GNU General Public 15 | * License (GPL) versions 2.0 or 3.0 as published by the Free Software 16 | * Foundation and appearing in the file LICENSE.GPL included in 17 | * the packaging of this file. Please review the following information 18 | * to ensure GNU General Public Licensing requirements will be met: 19 | * http://www.fsf.org/licensing/licenses/info/GPLv2.html and 20 | * http://www.gnu.org/copyleft/gpl.html. 21 | */ 22 | 23 | namespace Vl 24 | { 25 | namespace Constants 26 | { 27 | const char LangVerilog[] = "Verilog"; 28 | const char LangQmake[] = "Qmake"; 29 | const char LangSdf[] = "Sdf"; 30 | const char EditorId1[] = "Verilog.Editor"; 31 | const char TaskId[] = "Verilog.TaskId"; 32 | const char EditorDisplayName1[] = "Verilog Editor"; 33 | const char EditorId2[] = "Verilog.Project.Editor"; 34 | const char EditorDisplayName2[] = "Verilog Project Editor"; 35 | const char MimeType[] = "text/x-verilog"; 36 | const char ProjectMimeType[] = "text/x-verilogcreator-project"; 37 | const char EditorId3[] = "Verilog.Sdf.Editor"; 38 | const char EditorDisplayName3[] = "Sdf Editor"; 39 | const char SdfMimeType[] = "text/x-verilogcreator-sdf"; 40 | const char SettingsId[] = "Verilog.Settings"; 41 | const char EditorContextMenuId1[] = "VerilogEditor.ContextMenu"; 42 | const char EditorContextMenuId2[] = "VerilogProjectEditor.ContextMenu"; 43 | const char ToolsMenuId[] = "VerilogTools.ToolsMenu"; 44 | const char FindUsagesCmd[] = "VerilogEditor.FindUsages"; 45 | const char GotoOuterBlockCmd[] = "VerilogEditor.GotoOuterBlockCmd"; 46 | const char ReloadProjectCmd[] = "VerilogEditor.ReloadProjectCmd"; 47 | } 48 | } 49 | 50 | #endif // VLCONSTANTS_H 51 | -------------------------------------------------------------------------------- /VlPlugin.h: -------------------------------------------------------------------------------- 1 | #ifndef VERILOGCREATOR_H 2 | #define VERILOGCREATOR_H 3 | 4 | /* 5 | * Copyright 2018 Rochus Keller 6 | * 7 | * This file is part of the VerilogCreator plugin. 8 | * 9 | * The following is the license that applies to this copy of the 10 | * plugin. For a license to use the plugin under conditions 11 | * other than those described here, please email to me@rochus-keller.ch. 12 | * 13 | * GNU General Public License Usage 14 | * This file may be used under the terms of the GNU General Public 15 | * License (GPL) versions 2.0 or 3.0 as published by the Free Software 16 | * Foundation and appearing in the file LICENSE.GPL included in 17 | * the packaging of this file. Please review the following information 18 | * to ensure GNU General Public Licensing requirements will be met: 19 | * http://www.fsf.org/licensing/licenses/info/GPLv2.html and 20 | * http://www.gnu.org/copyleft/gpl.html. 21 | */ 22 | 23 | #include "verilogcreator_global.h" 24 | 25 | #include 26 | 27 | namespace Vl { class EditorWidget1; } 28 | class QAction; 29 | 30 | namespace VerilogCreator { 31 | namespace Internal { 32 | 33 | class VerilogCreatorPlugin : public ExtensionSystem::IPlugin 34 | { 35 | Q_OBJECT 36 | Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "VerilogCreator.json") 37 | 38 | public: 39 | VerilogCreatorPlugin(); 40 | ~VerilogCreatorPlugin(); 41 | 42 | static VerilogCreatorPlugin* instance(); 43 | 44 | bool initialize(const QStringList &arguments, QString *errorString); 45 | void extensionsInitialized(); 46 | ShutdownFlag aboutToShutdown(); 47 | 48 | public slots: 49 | void onFindUsages(); 50 | void onGotoOuterBlock(); 51 | void onReloadProject(); 52 | 53 | protected: 54 | Vl::EditorWidget1* currentEditorWidget(); 55 | void initializeToolsSettings(); 56 | static VerilogCreatorPlugin* d_instance; 57 | private: 58 | QAction* d_findUsagesAction; 59 | QAction* d_gotoOuterBlockAction; 60 | QAction* d_reloadProject; 61 | }; 62 | 63 | } // namespace Internal 64 | } // namespace VerilogCreator 65 | 66 | #endif // VERILOGCREATOR_H 67 | 68 | -------------------------------------------------------------------------------- /VlSdfEditor.h: -------------------------------------------------------------------------------- 1 | #ifndef VLSDFEDITOR_H 2 | #define VLSDFEDITOR_H 3 | 4 | /* 5 | * Copyright 2019 Rochus Keller 6 | * 7 | * This file is part of the VerilogCreator plugin. 8 | * 9 | * The following is the license that applies to this copy of the 10 | * plugin. For a license to use the plugin under conditions 11 | * other than those described here, please email to me@rochus-keller.ch. 12 | * 13 | * GNU General Public License Usage 14 | * This file may be used under the terms of the GNU General Public 15 | * License (GPL) versions 2.0 or 3.0 as published by the Free Software 16 | * Foundation and appearing in the file LICENSE.GPL included in 17 | * the packaging of this file. Please review the following information 18 | * to ensure GNU General Public Licensing requirements will be met: 19 | * http://www.fsf.org/licensing/licenses/info/GPLv2.html and 20 | * http://www.gnu.org/copyleft/gpl.html. 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | namespace Vl 29 | { 30 | class Editor3 : public TextEditor::BaseTextEditor 31 | { 32 | Q_OBJECT 33 | public: 34 | explicit Editor3(); 35 | 36 | }; 37 | 38 | class EditorFactory3 : public TextEditor::TextEditorFactory 39 | { 40 | Q_OBJECT 41 | public: 42 | EditorFactory3(); 43 | }; 44 | 45 | class EditorDocument3 : public TextEditor::TextDocument 46 | { 47 | Q_OBJECT 48 | public: 49 | EditorDocument3(); 50 | }; 51 | 52 | class EditorWidget3 : public TextEditor::TextEditorWidget 53 | { 54 | Q_OBJECT 55 | public: 56 | EditorWidget3() {} 57 | protected: 58 | void contextMenuEvent(QContextMenuEvent *e) Q_DECL_OVERRIDE; 59 | 60 | }; 61 | 62 | class Highlighter3 : public TextEditor::SyntaxHighlighter 63 | { 64 | public: 65 | Highlighter3(QTextDocument* = 0); 66 | void highlightBlock(const QString &text); 67 | private: 68 | QTextCharFormat formatForCategory(int i) const { return d_format[i]; } 69 | enum Category { C_Num, C_Str, C_Kw, C_Ident, C_Op, C_Cmt, C_Max }; 70 | QTextCharFormat d_format[C_Max]; 71 | }; 72 | } 73 | 74 | #endif // VLSDFEDITOR_H 75 | -------------------------------------------------------------------------------- /VlOutlineWidget.h: -------------------------------------------------------------------------------- 1 | #ifndef VLOUTLINEWIDGET_H 2 | #define VLOUTLINEWIDGET_H 3 | 4 | /* 5 | * Copyright 2019 Rochus Keller 6 | * 7 | * This file is part of the VerilogCreator plugin. 8 | * 9 | * The following is the license that applies to this copy of the 10 | * plugin. For a license to use the plugin under conditions 11 | * other than those described here, please email to me@rochus-keller.ch. 12 | * 13 | * GNU General Public License Usage 14 | * This file may be used under the terms of the GNU General Public 15 | * License (GPL) versions 2.0 or 3.0 as published by the Free Software 16 | * Foundation and appearing in the file LICENSE.GPL included in 17 | * the packaging of this file. Please review the following information 18 | * to ensure GNU General Public Licensing requirements will be met: 19 | * http://www.fsf.org/licensing/licenses/info/GPLv2.html and 20 | * http://www.gnu.org/copyleft/gpl.html. 21 | */ 22 | 23 | #include 24 | #include 25 | 26 | namespace Vl 27 | { 28 | class EditorWidget1; 29 | class OutlineMdl2; 30 | 31 | class OutlineTreeView : public Utils::NavigationTreeView 32 | { 33 | Q_OBJECT 34 | public: 35 | OutlineTreeView(QWidget *parent); 36 | 37 | void contextMenuEvent(QContextMenuEvent *event); 38 | }; 39 | 40 | class OutlineWidget : public TextEditor::IOutlineWidget 41 | { 42 | Q_OBJECT 43 | public: 44 | explicit OutlineWidget(EditorWidget1 *parent = 0); 45 | ~OutlineWidget(); 46 | 47 | // overrides 48 | QList filterMenuActions() const; 49 | void setCursorSynchronization(bool syncWithCursor); 50 | protected slots: 51 | void onItemActivated(QModelIndex); 52 | void onGotoSymbol( quint32 line, quint16 col ); 53 | private: 54 | EditorWidget1* d_edit; 55 | OutlineTreeView* d_tree; 56 | OutlineMdl2* d_mdl; 57 | bool d_enableCursorSync; 58 | bool d_blockCursorSync; 59 | }; 60 | 61 | class OutlineWidgetFactory : public TextEditor::IOutlineWidgetFactory 62 | { 63 | Q_OBJECT 64 | public: 65 | bool supportsEditor(Core::IEditor *editor) const; 66 | TextEditor::IOutlineWidget *createWidget(Core::IEditor *editor); 67 | }; 68 | } 69 | 70 | #endif // VLOUTLINEWIDGET_H 71 | -------------------------------------------------------------------------------- /VlIndenter.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Rochus Keller 3 | * 4 | * This file is part of the VerilogCreator plugin. 5 | * 6 | * The following is the license that applies to this copy of the 7 | * plugin. For a license to use the plugin under conditions 8 | * other than those described here, please email to me@rochus-keller.ch. 9 | * 10 | * GNU General Public License Usage 11 | * This file may be used under the terms of the GNU General Public 12 | * License (GPL) versions 2.0 or 3.0 as published by the Free Software 13 | * Foundation and appearing in the file LICENSE.GPL included in 14 | * the packaging of this file. Please review the following information 15 | * to ensure GNU General Public Licensing requirements will be met: 16 | * http://www.fsf.org/licensing/licenses/info/GPLv2.html and 17 | * http://www.gnu.org/copyleft/gpl.html. 18 | */ 19 | 20 | #include "VlIndenter.h" 21 | #include "VlHighlighter.h" 22 | #include 23 | #include 24 | using namespace Vl; 25 | 26 | static const int TAB_SIZE = 4; 27 | 28 | VerilogIndenter::VerilogIndenter() 29 | { 30 | 31 | } 32 | 33 | bool VerilogIndenter::isElectricCharacter(const QChar& ch) const 34 | { 35 | Q_UNUSED(ch); 36 | return false; 37 | } 38 | 39 | void VerilogIndenter::indentBlock(QTextDocument* doc, const QTextBlock& block, const QChar& typedChar, 40 | const TextEditor::TabSettings& tabSettings) 41 | { 42 | // aus QtCreator texteditor normalindenter adaptiert 43 | // TODO: später mal einen intelligenteren Indenter wie bei C++, ist aber nice to have. 44 | Q_UNUSED(typedChar) 45 | 46 | // At beginning: Leave as is. 47 | if (block == doc->begin()) 48 | return; 49 | 50 | const QTextBlock previous = block.previous(); 51 | const QString previousText = previous.text(); 52 | // Empty line indicates a start of a new paragraph. Leave as is. 53 | if (previousText.isEmpty() || previousText.trimmed().isEmpty()) 54 | return; 55 | 56 | // Just use previous line. 57 | // Skip blank characters when determining the indentation 58 | int i = 0; 59 | while (i < previousText.size()) { 60 | if (!previousText.at(i).isSpace()) { 61 | tabSettings.indentLine(block, tabSettings.columnAt(previousText, i)); 62 | break; 63 | } 64 | ++i; 65 | } 66 | } 67 | 68 | -------------------------------------------------------------------------------- /VlProjectEditor.h: -------------------------------------------------------------------------------- 1 | #ifndef VLPROJECTEDITOR_H 2 | #define VLPROJECTEDITOR_H 3 | 4 | /* 5 | * Copyright 2018 Rochus Keller 6 | * 7 | * This file is part of the VerilogCreator plugin. 8 | * 9 | * The following is the license that applies to this copy of the 10 | * plugin. For a license to use the plugin under conditions 11 | * other than those described here, please email to me@rochus-keller.ch. 12 | * 13 | * GNU General Public License Usage 14 | * This file may be used under the terms of the GNU General Public 15 | * License (GPL) versions 2.0 or 3.0 as published by the Free Software 16 | * Foundation and appearing in the file LICENSE.GPL included in 17 | * the packaging of this file. Please review the following information 18 | * to ensure GNU General Public Licensing requirements will be met: 19 | * http://www.fsf.org/licensing/licenses/info/GPLv2.html and 20 | * http://www.gnu.org/copyleft/gpl.html. 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | namespace Vl 29 | { 30 | 31 | class Editor2 : public TextEditor::BaseTextEditor 32 | { 33 | Q_OBJECT 34 | public: 35 | explicit Editor2(); 36 | 37 | }; 38 | 39 | class EditorFactory2 : public TextEditor::TextEditorFactory 40 | { 41 | Q_OBJECT 42 | public: 43 | EditorFactory2(); 44 | }; 45 | 46 | class EditorDocument2 : public TextEditor::TextDocument 47 | { 48 | Q_OBJECT 49 | public: 50 | EditorDocument2(); 51 | }; 52 | 53 | class EditorWidget2 : public TextEditor::TextEditorWidget 54 | { 55 | Q_OBJECT 56 | public: 57 | EditorWidget2(); 58 | protected: 59 | void contextMenuEvent(QContextMenuEvent *e) Q_DECL_OVERRIDE; 60 | 61 | }; 62 | 63 | class Highlighter2 : public TextEditor::SyntaxHighlighter 64 | { 65 | public: 66 | enum ProfileFormats { 67 | ProfileVariableFormat, 68 | ProfileFunctionFormat, 69 | ProfileCommentFormat, 70 | ProfileVisualWhitespaceFormat, 71 | NumProfileFormats 72 | }; 73 | 74 | explicit Highlighter2(const TextEditor::Keywords &keywords); 75 | void highlightBlock(const QString &text); 76 | 77 | private: 78 | const TextEditor::Keywords m_keywords; 79 | }; 80 | } 81 | 82 | #endif // VLPROJECTEDITOR_H 83 | -------------------------------------------------------------------------------- /VlModuleLocator.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Rochus Keller 3 | * 4 | * This file is part of the VerilogCreator plugin. 5 | * 6 | * The following is the license that applies to this copy of the 7 | * plugin. For a license to use the plugin under conditions 8 | * other than those described here, please email to me@rochus-keller.ch. 9 | * 10 | * GNU General Public License Usage 11 | * This file may be used under the terms of the GNU General Public 12 | * License (GPL) versions 2.0 or 3.0 as published by the Free Software 13 | * Foundation and appearing in the file LICENSE.GPL included in 14 | * the packaging of this file. Please review the following information 15 | * to ensure GNU General Public Licensing requirements will be met: 16 | * http://www.fsf.org/licensing/licenses/info/GPLv2.html and 17 | * http://www.gnu.org/copyleft/gpl.html. 18 | */ 19 | 20 | #include "VlModuleLocator.h" 21 | #include "VlModelManager.h" 22 | #include 23 | #include 24 | using namespace Vl; 25 | 26 | ModuleLocator::ModuleLocator() 27 | { 28 | setId("VerilogModules"); 29 | setDisplayName(tr("Verilog modules and UDPs in global namespace")); 30 | setShortcutString(QString(QLatin1Char('m'))); 31 | setIncludedByDefault(false); 32 | } 33 | 34 | QList ModuleLocator::matchesFor(QFutureInterface& future, 35 | const QString& entry) 36 | { 37 | Q_UNUSED(future); 38 | 39 | QList res; 40 | 41 | CrossRefModel* mdl = ModelManager::instance()->getModelForCurrentProject(); 42 | if( mdl == 0 ) 43 | return res; 44 | 45 | QDir path( ModelManager::instance()->getPathOf(mdl) ); 46 | 47 | CrossRefModel::IdentDeclRefList l = mdl->getGlobalNames(); 48 | 49 | QStringMatcher matcher(entry, Qt::CaseInsensitive); // ByteArrayMatcher is case sensitive instead 50 | 51 | QPixmap icon(":/verilogcreator/images/block.png"); 52 | foreach(const CrossRefModel::IdentDeclRef& id, l ) 53 | { 54 | const QString name = QString::fromLatin1(id->tok().d_val); 55 | if( matcher.indexIn( name ) != -1 ) 56 | { 57 | res << Core::LocatorFilterEntry( this, name, QVariant::fromValue(CrossRefModel::SymRef(id)),icon); 58 | res.last().extraInfo = path.relativeFilePath( id->tok().d_sourcePath ); 59 | } 60 | } 61 | return res; 62 | } 63 | 64 | void ModuleLocator::accept(Core::LocatorFilterEntry selection) const 65 | { 66 | CrossRefModel::SymRef sym = selection.internalData.value(); 67 | Core::EditorManager::openEditorAt( sym->tok().d_sourcePath, 68 | sym->tok().d_lineNr - 1, sym->tok().d_colNr + 0 ); 69 | } 70 | 71 | void ModuleLocator::refresh(QFutureInterface& future) 72 | { 73 | Q_UNUSED(future); 74 | } 75 | 76 | -------------------------------------------------------------------------------- /VlProject.h: -------------------------------------------------------------------------------- 1 | #ifndef VLPROJECT_H 2 | #define VLPROJECT_H 3 | 4 | /* 5 | * Copyright 2018 Rochus Keller 6 | * 7 | * This file is part of the VerilogCreator plugin. 8 | * 9 | * The following is the license that applies to this copy of the 10 | * plugin. For a license to use the plugin under conditions 11 | * other than those described here, please email to me@rochus-keller.ch. 12 | * 13 | * GNU General Public License Usage 14 | * This file may be used under the terms of the GNU General Public 15 | * License (GPL) versions 2.0 or 3.0 as published by the Free Software 16 | * Foundation and appearing in the file LICENSE.GPL included in 17 | * the packaging of this file. Please review the following information 18 | * to ensure GNU General Public Licensing requirements will be met: 19 | * http://www.fsf.org/licensing/licenses/info/GPLv2.html and 20 | * http://www.gnu.org/copyleft/gpl.html. 21 | */ 22 | 23 | #include 24 | 25 | #include 26 | #include 27 | 28 | namespace TextEditor { class TextDocument; } 29 | namespace ProjectExplorer { class FolderNode; } 30 | 31 | namespace Vl 32 | { 33 | class ProjectManager; 34 | class ProjectNode; 35 | 36 | class Project : public ProjectExplorer::Project 37 | { 38 | Q_OBJECT 39 | public: 40 | static const char* ID; 41 | 42 | explicit Project(ProjectManager *projectManager, const QString &fileName); 43 | 44 | const QStringList& getSrcFiles() const { return d_config.getSrcFiles(); } 45 | const QStringList& getLibFiles() const { return d_config.getLibFiles(); } 46 | QStringList getConfig( const QString& key ) const { return d_config.getConfig(key); } 47 | QStringList getIncDirs() const { return d_config.getIncDirs(); } 48 | QString getTopMod() const { return d_config.getTopMod(); } 49 | void reload(); 50 | 51 | // overrides 52 | QString displayName() const Q_DECL_OVERRIDE; 53 | Core::IDocument* document() const Q_DECL_OVERRIDE; 54 | ProjectExplorer::IProjectManager *projectManager() const Q_DECL_OVERRIDE; 55 | ProjectExplorer::ProjectNode *rootProjectNode() const Q_DECL_OVERRIDE; 56 | QStringList files(FilesMode) const Q_DECL_OVERRIDE; 57 | protected: 58 | void loadProject( const QString& fileName ); 59 | static void fillNode( const QStringList& files, ProjectExplorer::FolderNode* ); 60 | 61 | RestoreResult fromMap(const QVariantMap &map, QString *errorMessage) Q_DECL_OVERRIDE; 62 | protected slots: 63 | void onFileChanged(const QString& path); 64 | private: 65 | ProjectManager* d_projectManager; 66 | TextEditor::TextDocument* d_document; 67 | ProjectNode* d_root; 68 | QString d_name; 69 | ProjectConfig d_config; 70 | QFileSystemWatcher d_watcher; 71 | }; 72 | } 73 | 74 | #endif // VLPROJECT_H 75 | -------------------------------------------------------------------------------- /VlVerilogEditor.h: -------------------------------------------------------------------------------- 1 | #ifndef VLVERILOGEDITOR_H 2 | #define VLVERILOGEDITOR_H 3 | 4 | /* 5 | * Copyright 2018 Rochus Keller 6 | * 7 | * This file is part of the VerilogCreator plugin. 8 | * 9 | * The following is the license that applies to this copy of the 10 | * plugin. For a license to use the plugin under conditions 11 | * other than those described here, please email to me@rochus-keller.ch. 12 | * 13 | * GNU General Public License Usage 14 | * This file may be used under the terms of the GNU General Public 15 | * License (GPL) versions 2.0 or 3.0 as published by the Free Software 16 | * Foundation and appearing in the file LICENSE.GPL included in 17 | * the packaging of this file. Please review the following information 18 | * to ensure GNU General Public Licensing requirements will be met: 19 | * http://www.fsf.org/licensing/licenses/info/GPLv2.html and 20 | * http://www.gnu.org/copyleft/gpl.html. 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | namespace Core { class SearchResultItem; } 29 | 30 | namespace Vl 31 | { 32 | class Editor1 : public TextEditor::BaseTextEditor 33 | { 34 | Q_OBJECT 35 | public: 36 | explicit Editor1(); 37 | 38 | }; 39 | 40 | class EditorFactory1 : public TextEditor::TextEditorFactory 41 | { 42 | Q_OBJECT 43 | public: 44 | EditorFactory1(); 45 | }; 46 | 47 | class EditorDocument1 : public TextEditor::TextDocument 48 | { 49 | Q_OBJECT 50 | public: 51 | EditorDocument1(); 52 | ~EditorDocument1(); 53 | 54 | // overrides 55 | TextDocument::OpenResult open(QString *errorString, const QString &fileName, const QString &realFileName); 56 | bool save(QString *errorString, const QString &fileName, bool autoSave); 57 | 58 | signals: 59 | void sigLoaded(); 60 | void sigStartProcessing(); 61 | 62 | protected slots: 63 | void onChangedContents(); 64 | void onProcess(); 65 | private: 66 | QTimer d_processorTimer; 67 | bool d_opening; 68 | }; 69 | 70 | class EditorWidget1 : public TextEditor::TextEditorWidget 71 | { 72 | Q_OBJECT 73 | public: 74 | EditorWidget1(); 75 | ~EditorWidget1(); 76 | 77 | void finalizeInitialization(); // override 78 | 79 | signals: 80 | void sigGotoSymbol( quint32 line, quint16 col ); 81 | 82 | public slots: 83 | void onFindUsages(); 84 | void onGotoOuterBlock(); 85 | void onFileUpdated( const QString& ); 86 | void onStartProcessing(); 87 | 88 | protected: 89 | Link findLinkAt(const QTextCursor &, bool resolveTarget = true, 90 | bool inNextSplit = false) Q_DECL_OVERRIDE; 91 | void contextMenuEvent(QContextMenuEvent *e) Q_DECL_OVERRIDE; 92 | 93 | protected slots: 94 | void onUpdateIfDefsOut(); 95 | void onUpdateCodeWarnings(); 96 | void onCursor(); 97 | void onOpenEditor(const Core::SearchResultItem &item); 98 | void onDocReady(); 99 | void gotoSymbolInEditor(); 100 | void updateToolTip(); 101 | private: 102 | Utils::TreeViewComboBox* d_outline; 103 | }; 104 | 105 | } 106 | 107 | #endif // VLVERILOGEDITOR_H 108 | -------------------------------------------------------------------------------- /VlAutoCompleter.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Rochus Keller 3 | * 4 | * This file is part of the VerilogCreator plugin. 5 | * 6 | * The following is the license that applies to this copy of the 7 | * plugin. For a license to use the plugin under conditions 8 | * other than those described here, please email to me@rochus-keller.ch. 9 | * 10 | * GNU General Public License Usage 11 | * This file may be used under the terms of the GNU General Public 12 | * License (GPL) versions 2.0 or 3.0 as published by the Free Software 13 | * Foundation and appearing in the file LICENSE.GPL included in 14 | * the packaging of this file. Please review the following information 15 | * to ensure GNU General Public Licensing requirements will be met: 16 | * http://www.fsf.org/licensing/licenses/info/GPLv2.html and 17 | * http://www.gnu.org/copyleft/gpl.html. 18 | */ 19 | 20 | #include "VlAutoCompleter.h" 21 | #include "VlConstants.h" 22 | #include 23 | #include 24 | #include 25 | using namespace Vl; 26 | 27 | // borrowed parts from RubyCreator 28 | 29 | bool AutoCompleter::contextAllowsAutoParentheses(const QTextCursor& cursor, const QString& textToInsert) const 30 | { 31 | if (isInComment(cursor)) 32 | return false; 33 | 34 | QChar ch; 35 | 36 | if (!textToInsert.isEmpty()) 37 | ch = textToInsert.at(0); 38 | 39 | switch( ch.toLatin1() ) 40 | { 41 | case '"': 42 | case '(': 43 | case '[': 44 | case '{': 45 | case ')': 46 | case ']': 47 | case '}': 48 | return true; 49 | default: 50 | return false; 51 | } 52 | } 53 | 54 | bool AutoCompleter::contextAllowsElectricCharacters(const QTextCursor& cursor) const 55 | { 56 | return TextEditor::AutoCompleter::contextAllowsElectricCharacters(cursor); 57 | } 58 | 59 | bool AutoCompleter::isInComment(const QTextCursor& cursor) const 60 | { 61 | const int state = cursor.block().userState(); 62 | if( state != -1 && state & 0xff ) // Zeichen für Multiline Comment aus Highlighter 63 | return true; 64 | 65 | const QString line = cursor.block().text(); 66 | const int col = cursor.columnNumber(); 67 | const int pos = line.indexOf(QLatin1String("//") ); 68 | if (pos == -1 || pos > col ) 69 | return false; 70 | else 71 | return true; 72 | } 73 | 74 | bool AutoCompleter::isInString(const QTextCursor& cursor) const 75 | { 76 | return TextEditor::AutoCompleter::isInString(cursor); 77 | } 78 | 79 | QString AutoCompleter::insertMatchingBrace(const QTextCursor& cursor, const QString& text, QChar la, int* skippedChars) const 80 | { 81 | if (text.length() != 1) 82 | return QString(); 83 | 84 | const QChar ch = text.at(0); 85 | switch (ch.toLatin1()) 86 | { 87 | case '"': 88 | if (la != ch) 89 | return QString(ch); 90 | ++*skippedChars; 91 | break; 92 | case '(': 93 | return QStringLiteral(")"); 94 | 95 | case '[': 96 | return QStringLiteral("]"); 97 | 98 | case '{': 99 | return QStringLiteral("}"); 100 | 101 | case ')': 102 | case ']': 103 | case '}': 104 | case ';': 105 | if (la == ch) 106 | ++*skippedChars; 107 | break; 108 | 109 | default: 110 | break; 111 | } // end of switch 112 | 113 | return QString(); 114 | } 115 | 116 | QString AutoCompleter::insertParagraphSeparator(const QTextCursor& cursor) const 117 | { 118 | return TextEditor::AutoCompleter::insertParagraphSeparator(cursor); 119 | } 120 | 121 | -------------------------------------------------------------------------------- /VlOutlineMdl.h: -------------------------------------------------------------------------------- 1 | #ifndef VLOUTLINEMDL_H 2 | #define VLOUTLINEMDL_H 3 | 4 | /* 5 | * Copyright 2018 Rochus Keller 6 | * 7 | * This file is part of the VerilogCreator plugin. 8 | * 9 | * The following is the license that applies to this copy of the 10 | * plugin. For a license to use the plugin under conditions 11 | * other than those described here, please email to me@rochus-keller.ch. 12 | * 13 | * GNU General Public License Usage 14 | * This file may be used under the terms of the GNU General Public 15 | * License (GPL) versions 2.0 or 3.0 as published by the Free Software 16 | * Foundation and appearing in the file LICENSE.GPL included in 17 | * the packaging of this file. Please review the following information 18 | * to ensure GNU General Public Licensing requirements will be met: 19 | * http://www.fsf.org/licensing/licenses/info/GPLv2.html and 20 | * http://www.gnu.org/copyleft/gpl.html. 21 | */ 22 | 23 | #include 24 | #include 25 | 26 | namespace Vl 27 | { 28 | class OutlineMdl1 : public QAbstractItemModel 29 | { 30 | Q_OBJECT 31 | public: 32 | explicit OutlineMdl1(QObject *parent = 0); 33 | 34 | void setFile( const QString& ); 35 | 36 | const CrossRefModel::Symbol* getSymbol( const QModelIndex & ) const; 37 | QModelIndex findSymbol( const CrossRefModel::Symbol* ); 38 | QModelIndex findSymbol( quint32 line, quint16 col ); 39 | 40 | // overrides 41 | QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; 42 | QModelIndex parent(const QModelIndex &child) const; 43 | int rowCount(const QModelIndex &parent = QModelIndex()) const; 44 | int columnCount(const QModelIndex &parent = QModelIndex()) const; 45 | QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; 46 | Qt::ItemFlags flags(const QModelIndex &index) const; 47 | 48 | protected slots: 49 | void onCrmUpdated(const QString&); 50 | 51 | protected: 52 | void fillTop(); 53 | void fillSubs(const CrossRefModel::Branch*, const QByteArray& name ); 54 | 55 | private: 56 | struct Slot 57 | { 58 | CrossRefModel::SymRef d_sym; 59 | QByteArray d_name; 60 | bool operator<( const Slot& rhs ) const { return qstricmp( d_name, rhs.d_name ) < 0; } 61 | }; 62 | QList d_rows; 63 | QString d_file; 64 | CrossRefModel* d_crm; 65 | }; 66 | 67 | class OutlineMdl2 : public QAbstractItemModel 68 | { 69 | Q_OBJECT 70 | public: 71 | explicit OutlineMdl2(QObject *parent = 0); 72 | 73 | void setFile( const QString& ); 74 | const CrossRefModel::Symbol* getSymbol( const QModelIndex & ) const; 75 | QModelIndex findSymbol( quint32 line, quint16 col ); 76 | 77 | // overrides 78 | int columnCount ( const QModelIndex & parent = QModelIndex() ) const { return 1; } 79 | QVariant data ( const QModelIndex & index, int role = Qt::DisplayRole ) const; 80 | QModelIndex index ( int row, int column, const QModelIndex & parent = QModelIndex() ) const; 81 | QModelIndex parent ( const QModelIndex & index ) const; 82 | int rowCount ( const QModelIndex & parent = QModelIndex() ) const; 83 | Qt::ItemFlags flags ( const QModelIndex & index ) const; 84 | 85 | protected slots: 86 | void onCrmUpdated(const QString& file); 87 | 88 | private: 89 | struct Slot 90 | { 91 | CrossRefModel::SymRef d_sym; 92 | QList d_children; 93 | Slot* d_parent; 94 | Slot(Slot* p = 0):d_parent(p){ if( p ) p->d_children.append(this); } 95 | ~Slot() { foreach( Slot* s, d_children ) delete s; } 96 | }; 97 | void fill(Slot* super, const CrossRefModel::Symbol* sym, QListIterator&); 98 | void fillTop(); 99 | QModelIndex findSymbol(Slot*, quint32 line, quint16 col ) const; 100 | Slot d_root; 101 | QString d_file; 102 | CrossRefModel* d_crm; 103 | }; 104 | } 105 | 106 | #endif // VLOUTLINEMDL_H 107 | -------------------------------------------------------------------------------- /VlConfigurationFactory.h: -------------------------------------------------------------------------------- 1 | #ifndef VLCONFIGURATIONFACTORY_H 2 | #define VLCONFIGURATIONFACTORY_H 3 | 4 | /* 5 | * Copyright 2018 Rochus Keller 6 | * 7 | * This file is part of the VerilogCreator plugin. 8 | * 9 | * The following is the license that applies to this copy of the 10 | * plugin. For a license to use the plugin under conditions 11 | * other than those described here, please email to me@rochus-keller.ch. 12 | * 13 | * GNU General Public License Usage 14 | * This file may be used under the terms of the GNU General Public 15 | * License (GPL) versions 2.0 or 3.0 as published by the Free Software 16 | * Foundation and appearing in the file LICENSE.GPL included in 17 | * the packaging of this file. Please review the following information 18 | * to ensure GNU General Public Licensing requirements will be met: 19 | * http://www.fsf.org/licensing/licenses/info/GPLv2.html and 20 | * http://www.gnu.org/copyleft/gpl.html. 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | namespace Vl 28 | { 29 | class BuildConfigurationFactory : public ProjectExplorer::IBuildConfigurationFactory 30 | { 31 | Q_OBJECT 32 | public: 33 | explicit BuildConfigurationFactory(QObject *parent = 0); 34 | 35 | int priority(const ProjectExplorer::Target *parent) const; 36 | QList availableBuilds(const ProjectExplorer::Target *parent) const; 37 | int priority(const ProjectExplorer::Kit *k, const QString &projectPath) const; 38 | QList availableSetups(const ProjectExplorer::Kit *k, 39 | const QString &projectPath) const; 40 | ProjectExplorer::BuildConfiguration *create(ProjectExplorer::Target *parent, 41 | const ProjectExplorer::BuildInfo *info) const; 42 | 43 | bool canClone(const ProjectExplorer::Target *parent, ProjectExplorer::BuildConfiguration *source) const; 44 | ProjectExplorer::BuildConfiguration *clone(ProjectExplorer::Target *parent, ProjectExplorer::BuildConfiguration *source); 45 | bool canRestore(const ProjectExplorer::Target *parent, const QVariantMap &map) const; 46 | ProjectExplorer::BuildConfiguration *restore(ProjectExplorer::Target *parent, const QVariantMap &map); 47 | 48 | private: 49 | bool canHandle(const ProjectExplorer::Target *t) const; 50 | 51 | }; 52 | 53 | class MakeStepFactory : public ProjectExplorer::IBuildStepFactory 54 | { 55 | Q_OBJECT 56 | public: 57 | explicit MakeStepFactory(QObject *parent = 0); 58 | 59 | bool canCreate(ProjectExplorer::BuildStepList *parent, Core::Id id) const; 60 | ProjectExplorer::BuildStep *create(ProjectExplorer::BuildStepList *parent, Core::Id id); 61 | bool canClone(ProjectExplorer::BuildStepList *parent, 62 | ProjectExplorer::BuildStep *source) const; 63 | ProjectExplorer::BuildStep *clone(ProjectExplorer::BuildStepList *parent, 64 | ProjectExplorer::BuildStep *source); 65 | bool canRestore(ProjectExplorer::BuildStepList *parent, const QVariantMap &map) const; 66 | ProjectExplorer::BuildStep *restore(ProjectExplorer::BuildStepList *parent, 67 | const QVariantMap &map); 68 | 69 | QList availableCreationIds(ProjectExplorer::BuildStepList *bc) const; 70 | QString displayNameForId(Core::Id id) const; 71 | }; 72 | 73 | class RunConfigurationFactory : public ProjectExplorer::IRunConfigurationFactory 74 | { 75 | Q_OBJECT 76 | 77 | public: 78 | explicit RunConfigurationFactory(QObject *parent = 0); 79 | 80 | bool canCreate(ProjectExplorer::Target *parent, Core::Id id) const; 81 | bool canRestore(ProjectExplorer::Target *parent, const QVariantMap &map) const; 82 | bool canClone(ProjectExplorer::Target *parent, ProjectExplorer::RunConfiguration *product) const; 83 | ProjectExplorer::RunConfiguration* clone(ProjectExplorer::Target *parent, ProjectExplorer::RunConfiguration *product); 84 | 85 | QList availableCreationIds(ProjectExplorer::Target *parent, CreationMode mode) const; 86 | QString displayNameForId(Core::Id id) const; 87 | 88 | private: 89 | ProjectExplorer::RunConfiguration* doCreate(ProjectExplorer::Target *parent, Core::Id id); 90 | ProjectExplorer::RunConfiguration* doRestore(ProjectExplorer::Target *parent, 91 | const QVariantMap &map); 92 | }; 93 | } 94 | 95 | #endif // VLCONFIGURATIONFACTORY_H 96 | -------------------------------------------------------------------------------- /VlOutlineWidget.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Rochus Keller 3 | * 4 | * This file is part of the VerilogCreator plugin. 5 | * 6 | * The following is the license that applies to this copy of the 7 | * plugin. For a license to use the plugin under conditions 8 | * other than those described here, please email to me@rochus-keller.ch. 9 | * 10 | * GNU General Public License Usage 11 | * This file may be used under the terms of the GNU General Public 12 | * License (GPL) versions 2.0 or 3.0 as published by the Free Software 13 | * Foundation and appearing in the file LICENSE.GPL included in 14 | * the packaging of this file. Please review the following information 15 | * to ensure GNU General Public Licensing requirements will be met: 16 | * http://www.fsf.org/licensing/licenses/info/GPLv2.html and 17 | * http://www.gnu.org/copyleft/gpl.html. 18 | */ 19 | 20 | #include "VlOutlineWidget.h" 21 | #include "VlVerilogEditor.h" 22 | #include "VlOutlineMdl.h" 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | using namespace Vl; 30 | 31 | OutlineWidget::OutlineWidget(EditorWidget1 *parent) : TextEditor::IOutlineWidget(), 32 | d_edit(parent),d_enableCursorSync(true),d_blockCursorSync(false) 33 | { 34 | d_tree = new OutlineTreeView(this); 35 | QVBoxLayout* box = new QVBoxLayout(this); 36 | box->setMargin(0); 37 | box->setSpacing(0); 38 | box->addWidget(d_tree); 39 | // TODO box->addWidget(Core::ItemViewFind::createSearchableWrapper(d_tree)); 40 | 41 | d_mdl = new OutlineMdl2( this ); 42 | const QString fileName = parent->textDocument()->filePath().toString(); 43 | d_tree->setModel(d_mdl); 44 | connect(d_mdl,SIGNAL(modelReset()), d_tree, SLOT(expandAll()) ); 45 | d_mdl->setFile(fileName); 46 | 47 | connect(d_tree, SIGNAL(activated(QModelIndex)), this, SLOT(onItemActivated(QModelIndex))); 48 | connect(d_edit,SIGNAL(sigGotoSymbol(quint32,quint16)), this, SLOT(onGotoSymbol(quint32,quint16)) ); 49 | 50 | //qDebug() << "OutlineWidget creator"; 51 | } 52 | 53 | OutlineWidget::~OutlineWidget() 54 | { 55 | //qDebug() << "OutlineWidget destructor"; 56 | } 57 | 58 | QList OutlineWidget::filterMenuActions() const 59 | { 60 | return QList(); 61 | } 62 | 63 | void OutlineWidget::setCursorSynchronization(bool syncWithCursor) 64 | { 65 | d_enableCursorSync = syncWithCursor; 66 | if (d_enableCursorSync) 67 | ; // updateSelectionInTree(m_editor->outline()->modelIndex()); 68 | } 69 | 70 | void OutlineWidget::onItemActivated(QModelIndex index) 71 | { 72 | if (!index.isValid()) 73 | return; 74 | 75 | const CrossRefModel::Symbol* sym = d_mdl->getSymbol(index); 76 | if( sym ) 77 | { 78 | d_blockCursorSync = true; 79 | 80 | Core::EditorManager::cutForwardNavigationHistory(); 81 | Core::EditorManager::addCurrentPositionToNavigationHistory(); 82 | 83 | // line has to be 1 based, column 0 based! 84 | d_edit->gotoLine( sym->tok().d_lineNr, sym->tok().d_colNr - 1); 85 | d_blockCursorSync = false; 86 | } 87 | d_edit->setFocus(); 88 | } 89 | 90 | void OutlineWidget::onGotoSymbol(quint32 line, quint16 col) 91 | { 92 | if (!( d_enableCursorSync && !d_blockCursorSync ) ) 93 | return; 94 | 95 | QModelIndex index = d_mdl->findSymbol( line, col ); 96 | d_blockCursorSync = true; 97 | d_tree->setCurrentIndex(index); 98 | d_tree->scrollTo(index); 99 | d_blockCursorSync = false; 100 | } 101 | 102 | bool OutlineWidgetFactory::supportsEditor(Core::IEditor* editor) const 103 | { 104 | if (qobject_cast(editor)) 105 | return true; 106 | return false; 107 | } 108 | 109 | TextEditor::IOutlineWidget*OutlineWidgetFactory::createWidget(Core::IEditor* editor) 110 | { 111 | Editor1* e = qobject_cast(editor); 112 | EditorWidget1* w = qobject_cast(e->widget()); 113 | 114 | OutlineWidget *widget = new OutlineWidget(w); 115 | 116 | return widget; 117 | } 118 | 119 | 120 | OutlineTreeView::OutlineTreeView(QWidget* parent): 121 | Utils::NavigationTreeView(parent) 122 | { 123 | setExpandsOnDoubleClick(false); 124 | setDragEnabled(true); 125 | setDragDropMode(QAbstractItemView::DragOnly); 126 | setSortingEnabled(false); 127 | } 128 | 129 | void OutlineTreeView::contextMenuEvent(QContextMenuEvent* event) 130 | { 131 | if (!event) 132 | return; 133 | 134 | QMenu contextMenu; 135 | 136 | contextMenu.addAction(tr("Expand All"), this, SLOT(expandAll())); 137 | contextMenu.addAction(tr("Collapse All"), this, SLOT(collapseAll())); 138 | 139 | contextMenu.exec(event->globalPos()); 140 | 141 | event->accept(); 142 | } 143 | -------------------------------------------------------------------------------- /VlYosysConfiguration.h: -------------------------------------------------------------------------------- 1 | #ifndef VYOSYSCONFIGURATION_H 2 | #define VYOSYSCONFIGURATION_H 3 | 4 | /* 5 | * Copyright 2018 Rochus Keller 6 | * 7 | * This file is part of the VerilogCreator plugin. 8 | * 9 | * The following is the license that applies to this copy of the 10 | * plugin. For a license to use the plugin under conditions 11 | * other than those described here, please email to me@rochus-keller.ch. 12 | * 13 | * GNU General Public License Usage 14 | * This file may be used under the terms of the GNU General Public 15 | * License (GPL) versions 2.0 or 3.0 as published by the Free Software 16 | * Foundation and appearing in the file LICENSE.GPL included in 17 | * the packaging of this file. Please review the following information 18 | * to ensure GNU General Public Licensing requirements will be met: 19 | * http://www.fsf.org/licensing/licenses/info/GPLv2.html and 20 | * http://www.gnu.org/copyleft/gpl.html. 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | class QLabel; 30 | class QCheckBox; 31 | 32 | namespace Vl 33 | { 34 | class YosysBuildConfig : public ProjectExplorer::BuildConfiguration 35 | { 36 | Q_OBJECT 37 | public: 38 | static const char* ID; 39 | static const char* Name; 40 | 41 | explicit YosysBuildConfig(ProjectExplorer::Target *parent); 42 | 43 | ProjectExplorer::NamedWidget* createConfigWidget(); 44 | BuildType buildType() const; 45 | 46 | static ProjectExplorer::BuildConfiguration* create( ProjectExplorer::Target* parent, 47 | const ProjectExplorer::BuildInfo* info ); 48 | 49 | protected: 50 | YosysBuildConfig(ProjectExplorer::Target *parent, Core::Id id); 51 | YosysBuildConfig(ProjectExplorer::Target *parent, YosysBuildConfig *source); 52 | friend class BuildConfigurationFactory; 53 | friend class YosysBuildConfigWidget; 54 | }; 55 | 56 | class YosysBuildConfigWidget : public ProjectExplorer::NamedWidget 57 | { 58 | Q_OBJECT 59 | 60 | public: 61 | YosysBuildConfigWidget(YosysBuildConfig *bc); 62 | protected slots: 63 | void buildDirectoryChanged(); 64 | void environmentChanged(); 65 | private: 66 | Utils::PathChooser* d_buildPath; 67 | YosysBuildConfig* d_conf; 68 | }; 69 | 70 | class YosysMakeStep : public ProjectExplorer::AbstractProcessStep 71 | { 72 | Q_OBJECT 73 | public: 74 | static const char* ID; 75 | 76 | explicit YosysMakeStep(ProjectExplorer::BuildStepList *parent); 77 | 78 | bool init(); 79 | void run(QFutureInterface &fi); 80 | bool immutable() const { return false; } 81 | ProjectExplorer::BuildStepConfigWidget* createConfigWidget(); 82 | QVariantMap toMap() const; 83 | protected: 84 | QString makeCommand(const Utils::Environment &environment) const; 85 | bool fromMap(const QVariantMap &map); 86 | private: 87 | QString d_cmd; 88 | QString d_args; 89 | friend class YosysMakeStepWidget; 90 | }; 91 | 92 | class YosysMakeStepWidget : public ProjectExplorer::BuildStepConfigWidget 93 | { 94 | Q_OBJECT 95 | 96 | public: 97 | YosysMakeStepWidget(YosysMakeStep *makeStep); 98 | QString displayName() const; 99 | QString summaryText() const; 100 | 101 | private slots: 102 | void makeLineEditTextEdited(); 103 | void makeArgumentsLineEditTextEdited(); 104 | void updateMakeOverrrideLabel(); 105 | void updateDetails(); 106 | 107 | private: 108 | YosysMakeStep* d_step; 109 | QString d_summary; 110 | QLabel* d_cmdLabel; 111 | QLineEdit* d_cmd; 112 | QLineEdit* d_args; 113 | }; 114 | 115 | class YosysCleanStep : public ProjectExplorer::AbstractProcessStep 116 | { 117 | Q_OBJECT 118 | public: 119 | static const char* ID; 120 | 121 | explicit YosysCleanStep(ProjectExplorer::BuildStepList *parent); 122 | 123 | bool init(); 124 | void run(QFutureInterface &fi); 125 | bool immutable() const { return true; } 126 | ProjectExplorer::BuildStepConfigWidget* createConfigWidget(); 127 | }; 128 | 129 | class YosysCleanStepWidget : public ProjectExplorer::BuildStepConfigWidget 130 | { 131 | Q_OBJECT 132 | 133 | public: 134 | YosysCleanStepWidget(YosysCleanStep *makeStep); 135 | QString displayName() const; 136 | QString summaryText() const; 137 | }; 138 | } 139 | 140 | #endif // VYOSYSCONFIGURATION_H 141 | -------------------------------------------------------------------------------- /VerilogCreator.pro: -------------------------------------------------------------------------------- 1 | #/* 2 | #* Copyright 2018 Rochus Keller 3 | #* 4 | #* This file is part of the VerilogCreator plugin. 5 | #* 6 | #* The following is the license that applies to this copy of the 7 | #* plugin. For a license to use the plugin under conditions 8 | #* other than those described here, please email to me@rochus-keller.ch. 9 | #* 10 | #* GNU General Public License Usage 11 | #* This file may be used under the terms of the GNU General Public 12 | #* License (GPL) versions 2.0 or 3.0 as published by the Free Software 13 | #* Foundation and appearing in the file LICENSE.GPL included in 14 | #* the packaging of this file. Please review the following information 15 | #* to ensure GNU General Public Licensing requirements will be met: 16 | #* http://www.fsf.org/licensing/licenses/info/GPLv2.html and 17 | #* http://www.gnu.org/copyleft/gpl.html. 18 | #*/ 19 | 20 | DEFINES += VERILOGCREATOR_LIBRARY 21 | 22 | # Qt Creator linking 23 | 24 | ## set the QTC_SOURCE environment variable to override the setting here 25 | QTCREATOR_SOURCES = $$(QTC_SOURCE) 26 | isEmpty(QTCREATOR_SOURCES):QTCREATOR_SOURCES=../QtcVerilog 27 | 28 | ## set the QTC_BUILD environment variable to override the setting here 29 | IDE_BUILD_TREE = $$(QTC_BUILD) 30 | isEmpty(IDE_BUILD_TREE):IDE_BUILD_TREE=../QtcVerilogBuild 31 | 32 | ###### If the plugin can be depended upon by other plugins, this code needs to be outsourced to 33 | ###### _dependencies.pri, where is the name of the directory containing the 34 | ###### plugin's sources. 35 | 36 | QTC_PLUGIN_NAME = VerilogCreator 37 | QTC_LIB_DEPENDS += \ 38 | # nothing here at this time 39 | 40 | QTC_PLUGIN_DEPENDS += \ 41 | coreplugin texteditor projectexplorer 42 | 43 | QTC_PLUGIN_RECOMMENDS += \ 44 | # optional plugin dependencies. nothing here at this time 45 | 46 | ###### End _dependencies.pri contents ###### 47 | 48 | include($$QTCREATOR_SOURCES/src/qtcreatorplugin.pri) 49 | 50 | ## uncomment to build plugin into user config directory 51 | ## /plugins/ 52 | ## where is e.g. 53 | ## "%LOCALAPPDATA%\QtProject\qtcreator" on Windows Vista and later 54 | ## "$XDG_DATA_HOME/data/QtProject/qtcreator" or "~/.local/share/data/QtProject/qtcreator" on Linux 55 | ## "~/Library/Application Support/QtProject/Qt Creator" on Mac 56 | isEmpty(QTC_VERILOG) { 57 | message(Use user destdir) 58 | USE_USER_DESTDIR = yes 59 | } 60 | 61 | VL_COMPAT_VERSION_LIST=$$split(QTCREATOR_COMPAT_VERSION,.) 62 | VL_COMPAT_VER_MAJ=$$format_number($$member(VL_COMPAT_VERSION_LIST,0), width=2 zeropad) 63 | VL_COMPAT_VER_MIN=$$format_number($$member(VL_COMPAT_VERSION_LIST,1), width=2 zeropad) 64 | DEFINES += "VL_QTC_VER_MAJ=$$VL_COMPAT_VER_MAJ" # 03 65 | DEFINES += "VL_QTC_VER_MIN=$$VL_COMPAT_VER_MIN" # 04 66 | DEFINES += "VL_QTC_VER=$$VL_COMPAT_VER_MAJ$$VL_COMPAT_VER_MIN" # 0304 67 | #message($$DEFINES) 68 | 69 | DEFINES -= QT_NO_CAST_FROM_ASCII 70 | 71 | # VerilogCreator files 72 | 73 | CONFIG(debug, debug|release) { 74 | DEFINES += _DEBUG 75 | } 76 | !win32 { QMAKE_CXXFLAGS += -Wno-reorder -Wno-unused-parameter -Wno-unused-function -Wno-unused-variable } 77 | 78 | INCLUDEPATH += .. 79 | 80 | SOURCES += \ 81 | VlHighlighter.cpp \ 82 | VlPlugin.cpp \ 83 | VlIndenter.cpp \ 84 | VlModelManager.cpp \ 85 | VlProject.cpp \ 86 | VlProjectManager.cpp \ 87 | VlHoverHandler.cpp \ 88 | VlConfigurationFactory.cpp \ 89 | VlIcarusConfiguration.cpp \ 90 | VlVerilatorConfiguration.cpp \ 91 | VlYosysConfiguration.cpp \ 92 | VlOutlineMdl.cpp \ 93 | VlTclConfiguration.cpp \ 94 | VlTclEngine.cpp \ 95 | VlAutoCompleter.cpp \ 96 | VlCompletionAssistProvider.cpp \ 97 | VlOutlineWidget.cpp \ 98 | VlModuleLocator.cpp \ 99 | VlSymbolLocator.cpp \ 100 | VlVerilogEditor.cpp \ 101 | VlProjectEditor.cpp \ 102 | VlSdfEditor.cpp 103 | 104 | HEADERS += \ 105 | verilogcreator_global.h \ 106 | VlHighlighter.h \ 107 | VlConstants.h \ 108 | VlPlugin.h \ 109 | VlIndenter.h \ 110 | VlModelManager.h \ 111 | VlProject.h \ 112 | VlProjectManager.h \ 113 | VlHoverHandler.h \ 114 | VlConfigurationFactory.h \ 115 | VlIcarusConfiguration.h \ 116 | VlVerilatorConfiguration.h \ 117 | VlYosysConfiguration.h \ 118 | VlOutlineMdl.h \ 119 | VlTclConfiguration.h \ 120 | VlTclEngine.h \ 121 | VlAutoCompleter.h \ 122 | VlCompletionAssistProvider.h \ 123 | VlOutlineWidget.h \ 124 | VlModuleLocator.h \ 125 | VlSymbolLocator.h \ 126 | VlVerilogEditor.h \ 127 | VlProjectEditor.h \ 128 | VlSdfEditor.h 129 | 130 | include (../Verilog/Verilog.pri ) 131 | include (../Sdf/Sdf.pri ) 132 | 133 | OTHER_FILES += 134 | 135 | DISTFILES += \ 136 | VerilogCreator.json.in 137 | 138 | RESOURCES += \ 139 | VerilogCreator.qrc 140 | -------------------------------------------------------------------------------- /VlVerilatorConfiguration.h: -------------------------------------------------------------------------------- 1 | #ifndef VVERILATORCONFIGURATION_H 2 | #define VVERILATORCONFIGURATION_H 3 | 4 | /* 5 | * Copyright 2018 Rochus Keller 6 | * 7 | * This file is part of the VerilogCreator plugin. 8 | * 9 | * The following is the license that applies to this copy of the 10 | * plugin. For a license to use the plugin under conditions 11 | * other than those described here, please email to me@rochus-keller.ch. 12 | * 13 | * GNU General Public License Usage 14 | * This file may be used under the terms of the GNU General Public 15 | * License (GPL) versions 2.0 or 3.0 as published by the Free Software 16 | * Foundation and appearing in the file LICENSE.GPL included in 17 | * the packaging of this file. Please review the following information 18 | * to ensure GNU General Public Licensing requirements will be met: 19 | * http://www.fsf.org/licensing/licenses/info/GPLv2.html and 20 | * http://www.gnu.org/copyleft/gpl.html. 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | class QLabel; 30 | class QCheckBox; 31 | 32 | namespace Vl 33 | { 34 | class VerilatorBuildConfig : public ProjectExplorer::BuildConfiguration 35 | { 36 | Q_OBJECT 37 | public: 38 | static const char* ID; 39 | static const char* Name; 40 | 41 | explicit VerilatorBuildConfig(ProjectExplorer::Target *parent); 42 | 43 | ProjectExplorer::NamedWidget* createConfigWidget(); 44 | BuildType buildType() const; 45 | 46 | static ProjectExplorer::BuildConfiguration* create( ProjectExplorer::Target* parent, 47 | const ProjectExplorer::BuildInfo* info ); 48 | 49 | protected: 50 | VerilatorBuildConfig(ProjectExplorer::Target *parent, Core::Id id); 51 | VerilatorBuildConfig(ProjectExplorer::Target *parent, VerilatorBuildConfig *source); 52 | friend class BuildConfigurationFactory; 53 | friend class VerilatorBuildConfigWidget; 54 | }; 55 | 56 | class VerilatorBuildConfigWidget : public ProjectExplorer::NamedWidget 57 | { 58 | Q_OBJECT 59 | 60 | public: 61 | VerilatorBuildConfigWidget(VerilatorBuildConfig *bc); 62 | protected slots: 63 | void buildDirectoryChanged(); 64 | void environmentChanged(); 65 | private: 66 | Utils::PathChooser* d_buildPath; 67 | VerilatorBuildConfig* d_conf; 68 | }; 69 | 70 | class VerilatorMakeStep : public ProjectExplorer::AbstractProcessStep 71 | { 72 | Q_OBJECT 73 | public: 74 | static const char* ID; 75 | 76 | explicit VerilatorMakeStep(ProjectExplorer::BuildStepList *parent); 77 | 78 | bool init(); 79 | void run(QFutureInterface &fi); 80 | bool immutable() const { return false; } 81 | ProjectExplorer::BuildStepConfigWidget* createConfigWidget(); 82 | QVariantMap toMap() const; 83 | protected: 84 | QString makeCommand(const Utils::Environment &environment) const; 85 | bool fromMap(const QVariantMap &map); 86 | private: 87 | QString d_cmd; 88 | QString d_args; 89 | friend class VerilatorMakeStepWidget; 90 | }; 91 | 92 | class VerilatorMakeStepWidget : public ProjectExplorer::BuildStepConfigWidget 93 | { 94 | Q_OBJECT 95 | 96 | public: 97 | VerilatorMakeStepWidget(VerilatorMakeStep *makeStep); 98 | QString displayName() const; 99 | QString summaryText() const; 100 | 101 | private slots: 102 | void makeLineEditTextEdited(); 103 | void makeArgumentsLineEditTextEdited(); 104 | void updateMakeOverrrideLabel(); 105 | void updateDetails(); 106 | 107 | private: 108 | VerilatorMakeStep* d_step; 109 | QString d_summary; 110 | QLabel* d_cmdLabel; 111 | QLineEdit* d_cmd; 112 | QLineEdit* d_args; 113 | }; 114 | 115 | class VerilatorCleanStep : public ProjectExplorer::AbstractProcessStep 116 | { 117 | Q_OBJECT 118 | public: 119 | static const char* ID; 120 | 121 | explicit VerilatorCleanStep(ProjectExplorer::BuildStepList *parent); 122 | 123 | bool init(); 124 | void run(QFutureInterface &fi); 125 | bool immutable() const { return true; } 126 | ProjectExplorer::BuildStepConfigWidget* createConfigWidget(); 127 | }; 128 | 129 | class VerilatorCleanStepWidget : public ProjectExplorer::BuildStepConfigWidget 130 | { 131 | Q_OBJECT 132 | 133 | public: 134 | VerilatorCleanStepWidget(VerilatorCleanStep *makeStep); 135 | QString displayName() const; 136 | QString summaryText() const; 137 | }; 138 | } 139 | 140 | #endif // VVERILATORCONFIGURATION_H 141 | -------------------------------------------------------------------------------- /VlSymbolLocator.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Rochus Keller 3 | * 4 | * This file is part of the VerilogCreator plugin. 5 | * 6 | * The following is the license that applies to this copy of the 7 | * plugin. For a license to use the plugin under conditions 8 | * other than those described here, please email to me@rochus-keller.ch. 9 | * 10 | * GNU General Public License Usage 11 | * This file may be used under the terms of the GNU General Public 12 | * License (GPL) versions 2.0 or 3.0 as published by the Free Software 13 | * Foundation and appearing in the file LICENSE.GPL included in 14 | * the packaging of this file. Please review the following information 15 | * to ensure GNU General Public Licensing requirements will be met: 16 | * http://www.fsf.org/licensing/licenses/info/GPLv2.html and 17 | * http://www.gnu.org/copyleft/gpl.html. 18 | */ 19 | 20 | #include "VlSymbolLocator.h" 21 | #include "VlModelManager.h" 22 | #include 23 | #include 24 | using namespace Vl; 25 | 26 | SymbolLocator::SymbolLocator() 27 | { 28 | setId("VerilogSymbols"); 29 | setDisplayName(tr("Verilog symbols in current document")); 30 | setShortcutString(QString(QLatin1Char('.'))); 31 | setIncludedByDefault(false); 32 | } 33 | 34 | static bool lessThan(const Core::LocatorFilterEntry&s1, const Core::LocatorFilterEntry&s2) 35 | { 36 | return s1.displayName.compare( s2.displayName, Qt::CaseInsensitive ) < 0 || 37 | ( !(s2.displayName.compare( s1.displayName, Qt::CaseInsensitive ) < 0) 38 | && s1.extraInfo.compare( s2.extraInfo, Qt::CaseInsensitive ) < 0 ); 39 | } 40 | 41 | QList SymbolLocator::matchesFor(QFutureInterface& future, const QString& entry) 42 | { 43 | Q_UNUSED(future); 44 | 45 | QList res; 46 | 47 | CrossRefModel* mdl = ModelManager::instance()->getModelForCurrentProject(); 48 | if( mdl == 0 ) 49 | return res; 50 | 51 | const QString fileName = Core::EditorManager::instance()->currentDocument() ? 52 | Core::EditorManager::instance()->currentDocument()->filePath().toString() : QString(); 53 | if( fileName.isEmpty() ) 54 | return res; 55 | 56 | CrossRefModel::IdentDeclRefList l = mdl->getGlobalNames(); 57 | 58 | QStringMatcher matcher(entry, Qt::CaseInsensitive); // ByteArrayMatcher is case sensitive instead 59 | 60 | QPixmap iMod(":/verilogcreator/images/block.png"); 61 | QPixmap iVar(":/verilogcreator/images/var.png"); 62 | QPixmap iFunc(":/verilogcreator/images/func.png"); 63 | 64 | foreach(const CrossRefModel::IdentDeclRef& id, l ) 65 | { 66 | if( id->tok().d_sourcePath != fileName ) 67 | continue; 68 | 69 | const QString name = QString::fromLatin1(id->tok().d_val); 70 | if( matcher.indexIn( name ) != -1 ) 71 | { 72 | res << Core::LocatorFilterEntry( this, name, QVariant::fromValue(CrossRefModel::SymRef(id)),iMod); 73 | res.back().extraInfo = QString("(%1)").arg( SynTree::rToStr( id->decl()->tok().d_type ) ); 74 | } 75 | const CrossRefModel::Scope* s = id->decl()->toScope(); 76 | if( s ) 77 | { 78 | foreach( const CrossRefModel::IdentDeclRef& id2, s->getNames() ) 79 | { 80 | const QString name2 = QString::fromLatin1(id2->tok().d_val); 81 | if( matcher.indexIn( name2 ) != -1 ) 82 | { 83 | const int type = id2->decl()->tok().d_type; 84 | QPixmap icon; 85 | switch(type) 86 | { 87 | case SynTree::R_task_declaration: 88 | case SynTree::R_function_declaration: 89 | icon = iFunc; 90 | break; 91 | default: 92 | icon = iVar; 93 | break; 94 | } 95 | res << Core::LocatorFilterEntry( this, name2, QVariant::fromValue(CrossRefModel::SymRef(id2)), icon ); 96 | // res << Core::LocatorFilterEntry( this, QString("%1.%2").arg(name).arg(name2), 97 | // QVariant::fromValue(CrossRefModel::SymRef(id2)), icon ); 98 | res.back().extraInfo = QString("%1 (%2)").arg(name).arg( SynTree::rToStr( type ) ); 99 | //res.back().extraInfo = QString("(%1)").arg( SynTree::rToStr( type ) ); 100 | } 101 | } 102 | } 103 | 104 | } 105 | std::sort( res.begin(), res.end(), lessThan ); 106 | return res; 107 | } 108 | 109 | void SymbolLocator::accept(Core::LocatorFilterEntry selection) const 110 | { 111 | CrossRefModel::SymRef sym = selection.internalData.value(); 112 | Core::EditorManager::openEditorAt( sym->tok().d_sourcePath, 113 | sym->tok().d_lineNr - 1, sym->tok().d_colNr + 0 ); 114 | } 115 | 116 | void SymbolLocator::refresh(QFutureInterface& future) 117 | { 118 | Q_UNUSED(future); 119 | } 120 | 121 | -------------------------------------------------------------------------------- /VlTclConfiguration.h: -------------------------------------------------------------------------------- 1 | #ifndef VLTCLCONFIGURATION_H 2 | #define VLTCLCONFIGURATION_H 3 | 4 | /* 5 | * Copyright 2018 Rochus Keller 6 | * 7 | * This file is part of the VerilogCreator plugin. 8 | * 9 | * The following is the license that applies to this copy of the 10 | * plugin. For a license to use the plugin under conditions 11 | * other than those described here, please email to me@rochus-keller.ch. 12 | * 13 | * GNU General Public License Usage 14 | * This file may be used under the terms of the GNU General Public 15 | * License (GPL) versions 2.0 or 3.0 as published by the Free Software 16 | * Foundation and appearing in the file LICENSE.GPL included in 17 | * the packaging of this file. Please review the following information 18 | * to ensure GNU General Public Licensing requirements will be met: 19 | * http://www.fsf.org/licensing/licenses/info/GPLv2.html and 20 | * http://www.gnu.org/copyleft/gpl.html. 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | class QLabel; 30 | class QCheckBox; 31 | 32 | namespace Vl 33 | { 34 | class TclBuildConfig : public ProjectExplorer::BuildConfiguration 35 | { 36 | Q_OBJECT 37 | public: 38 | static const char* ID; 39 | 40 | explicit TclBuildConfig(ProjectExplorer::Target *parent); 41 | ~TclBuildConfig(); 42 | 43 | ProjectExplorer::NamedWidget* createConfigWidget(); 44 | BuildType buildType() const; 45 | 46 | static ProjectExplorer::BuildConfiguration* create( ProjectExplorer::Target* parent, 47 | const ProjectExplorer::BuildInfo* info ); 48 | 49 | protected: 50 | TclBuildConfig(ProjectExplorer::Target *parent, Core::Id id); 51 | TclBuildConfig(ProjectExplorer::Target *parent, TclBuildConfig *source); 52 | friend class BuildConfigurationFactory; 53 | friend class TclBuildConfigWidget; 54 | }; 55 | 56 | class TclBuildConfigWidget : public ProjectExplorer::NamedWidget 57 | { 58 | Q_OBJECT 59 | 60 | public: 61 | TclBuildConfigWidget(TclBuildConfig *bc); 62 | protected slots: 63 | void buildDirectoryChanged(); 64 | void environmentChanged(); 65 | private: 66 | Utils::PathChooser* d_buildPath; 67 | TclBuildConfig* d_conf; 68 | }; 69 | 70 | class TclEngine; 71 | 72 | class TclStep : public ProjectExplorer::AbstractProcessStep 73 | { 74 | Q_OBJECT 75 | public: 76 | static const char* ID; 77 | 78 | explicit TclStep(ProjectExplorer::BuildStepList *parent); 79 | ~TclStep(); 80 | 81 | bool init(); 82 | void run(QFutureInterface &fi); 83 | bool immutable() const { return false; } 84 | ProjectExplorer::BuildStepConfigWidget* createConfigWidget(); 85 | QVariantMap toMap() const; 86 | protected: 87 | QString makeCommand(const Utils::Environment &environment) const; 88 | bool fromMap(const QVariantMap &map); 89 | static void writeLog(const QByteArray& msg, bool err, void* data); 90 | static QStringList tclGetVar(const QByteArray& name, void* data); 91 | private: 92 | QString d_scriptFile; 93 | TclEngine* d_tcl; 94 | friend class TclMakeStepWidget; 95 | }; 96 | 97 | class TclMakeStepWidget : public ProjectExplorer::BuildStepConfigWidget 98 | { 99 | Q_OBJECT 100 | 101 | public: 102 | TclMakeStepWidget(TclStep *makeStep); 103 | QString displayName() const; 104 | QString summaryText() const; 105 | 106 | private slots: 107 | void makeLineEditTextEdited(); 108 | void updateDetails(); 109 | void onBrowse(); 110 | 111 | private: 112 | TclStep* d_step; 113 | QString d_summary; 114 | QLineEdit* d_scriptFile; 115 | }; 116 | 117 | class TclRunConfiguration : public ProjectExplorer::LocalApplicationRunConfiguration 118 | { 119 | Q_OBJECT 120 | public: 121 | static const char* ID; 122 | static const char* Name; 123 | 124 | virtual QWidget* createConfigurationWidget(); 125 | virtual QString executable() const; 126 | virtual ProjectExplorer::ApplicationLauncher::Mode runMode() const; 127 | virtual QString workingDirectory() const; 128 | virtual QString commandLineArguments() const; 129 | virtual void addToBaseEnvironment(Utils::Environment &env) const; 130 | QVariantMap toMap() const; 131 | 132 | protected: 133 | explicit TclRunConfiguration(ProjectExplorer::Target *target); 134 | explicit TclRunConfiguration(ProjectExplorer::Target *target, TclRunConfiguration *rc); 135 | virtual bool fromMap(const QVariantMap &map); 136 | friend class RunConfigurationFactory; 137 | friend class TclRunConfigWidget; 138 | private: 139 | QString d_scriptFile; 140 | bool d_terminal; 141 | }; 142 | 143 | class TclRunConfigWidget : public QWidget 144 | { 145 | Q_OBJECT 146 | public: 147 | TclRunConfigWidget( TclRunConfiguration* ); 148 | private slots: 149 | void cmdEdited(); 150 | void termChanged(); 151 | private: 152 | TclRunConfiguration* d_cfg; 153 | QLineEdit* d_scriptFile; 154 | QCheckBox* d_term; 155 | }; 156 | } 157 | 158 | #endif // VLTCLCONFIGURATION_H 159 | -------------------------------------------------------------------------------- /VlModelManager.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Rochus Keller 3 | * 4 | * This file is part of the VerilogCreator plugin. 5 | * 6 | * The following is the license that applies to this copy of the 7 | * plugin. For a license to use the plugin under conditions 8 | * other than those described here, please email to me@rochus-keller.ch. 9 | * 10 | * GNU General Public License Usage 11 | * This file may be used under the terms of the GNU General Public 12 | * License (GPL) versions 2.0 or 3.0 as published by the Free Software 13 | * Foundation and appearing in the file LICENSE.GPL included in 14 | * the packaging of this file. Please review the following information 15 | * to ensure GNU General Public Licensing requirements will be met: 16 | * http://www.fsf.org/licensing/licenses/info/GPLv2.html and 17 | * http://www.gnu.org/copyleft/gpl.html. 18 | */ 19 | 20 | #include "VlModelManager.h" 21 | #include "VlConstants.h" 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | using namespace Vl; 29 | 30 | ModelManager* ModelManager::d_inst = 0; 31 | 32 | ModelManager::ModelManager(QObject *parent) : QObject(parent),d_lastUsed(0) 33 | { 34 | d_fcache = new FileCache(this); 35 | d_inst = this; 36 | } 37 | 38 | ModelManager::~ModelManager() 39 | { 40 | // Lösche hier explizit damit nicht FileCache gelöscht wird während noch Threads laufen 41 | QHash::const_iterator i; 42 | for( i = d_models.begin(); i != d_models.end(); ++i ) 43 | delete i.value(); 44 | d_inst = 0; 45 | } 46 | 47 | CrossRefModel*ModelManager::getModelForFile(const QString& fileName) 48 | { 49 | if( fileName.isEmpty() ) 50 | return d_lastUsed; 51 | CrossRefModel*& m = d_models[fileName]; 52 | if( m == 0 ) 53 | { 54 | m = new CrossRefModel(this,d_fcache); 55 | connect( m, SIGNAL(sigModelUpdated()), this, SLOT(onModelUpdated()) ); 56 | d_paths[m] = fileName; 57 | } 58 | d_lastUsed = m; 59 | return m; 60 | } 61 | 62 | CrossRefModel*ModelManager::getModelForDir(const QString& dirPath, bool initIfEmpty ) 63 | { 64 | if( dirPath.isEmpty() ) 65 | return 0; 66 | QFileInfo info(dirPath); 67 | CrossRefModel* mdl = getModelForFile( info.path() ); 68 | if( initIfEmpty && mdl->isEmpty() ) 69 | { 70 | QDir dir = info.dir(); 71 | QStringList files = dir.entryList( QStringList() << QString("*.v") 72 | << QString("*.vl"), QDir::Files, QDir::Name ); 73 | for( int i = 0; i < files.size(); i++ ) 74 | files[i] = dir.absoluteFilePath(files[i]); 75 | mdl->updateFiles(files); 76 | } 77 | return mdl; 78 | } 79 | 80 | CrossRefModel*ModelManager::getModelForCurrentProject() 81 | { 82 | CrossRefModel* mdl = 0; 83 | ProjectExplorer::Project *currentProject = ProjectExplorer::ProjectTree::currentProject(); 84 | if( currentProject ) 85 | mdl = getModelForFile(currentProject->projectFilePath().toString()); 86 | if( mdl == 0 ) 87 | mdl = getLastUsed(); 88 | return mdl; 89 | } 90 | 91 | CrossRefModel*ModelManager::getModelForCurrentProjectOrDirPath(const QString& dirPath, bool initIfEmpty) 92 | { 93 | CrossRefModel* mdl = ModelManager::instance()->getModelForCurrentProject(); 94 | if( mdl == 0 ) 95 | mdl = ModelManager::instance()->getModelForDir(dirPath, initIfEmpty); 96 | return mdl; 97 | } 98 | 99 | QString ModelManager::getPathOf(CrossRefModel* m) const 100 | { 101 | return d_paths.value(m); 102 | } 103 | 104 | ModelManager*ModelManager::instance() 105 | { 106 | if( d_inst ) 107 | return d_inst; 108 | new ModelManager(); 109 | return d_inst; 110 | } 111 | 112 | void ModelManager::onModelUpdated() 113 | { 114 | // TODO: optional ein- oder ausschaltbar 115 | 116 | CrossRefModel* mdl = static_cast( sender() ); 117 | 118 | ProjectExplorer::TaskHub::clearTasks( Vl::Constants::TaskId ); 119 | 120 | typedef QPair FileLine; 121 | typedef QPair Message; 122 | typedef QMultiMap Lines; 123 | Lines lines; 124 | Errors::EntriesByFile errs = mdl->getErrs()->getErrors(); 125 | for( Errors::EntriesByFile::const_iterator j = errs.begin(); j != errs.end(); ++j ) 126 | { 127 | foreach (const Errors::Entry& e, j.value() ) 128 | { 129 | lines.insert( qMakePair( j.key(), e.d_line ), qMakePair( e.d_msg, true ) ); 130 | } 131 | } 132 | Errors::EntriesByFile wrns = mdl->getErrs()->getWarnings(); 133 | for( Errors::EntriesByFile::const_iterator j = wrns.begin(); j != wrns.end(); ++j ) 134 | { 135 | foreach (const Errors::Entry& e, j.value() ) 136 | { 137 | lines.insert( qMakePair( j.key(), e.d_line ), qMakePair( e.d_msg, false ) ); 138 | } 139 | } 140 | 141 | for( Lines::const_iterator i = lines.begin(); i != lines.end(); ++i ) 142 | { 143 | // TaskHub sortiert nicht selber 144 | ProjectExplorer::TaskHub::addTask( i.value().second ? ProjectExplorer::Task::Error : ProjectExplorer::Task::Warning, 145 | i.value().first, 146 | Vl::Constants::TaskId, 147 | Utils::FileName::fromString(i.key().first), 148 | i.key().second ); 149 | } 150 | } 151 | 152 | -------------------------------------------------------------------------------- /VlHoverHandler.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Rochus Keller 3 | * 4 | * This file is part of the VerilogCreator plugin. 5 | * 6 | * The following is the license that applies to this copy of the 7 | * plugin. For a license to use the plugin under conditions 8 | * other than those described here, please email to me@rochus-keller.ch. 9 | * 10 | * GNU General Public License Usage 11 | * This file may be used under the terms of the GNU General Public 12 | * License (GPL) versions 2.0 or 3.0 as published by the Free Software 13 | * Foundation and appearing in the file LICENSE.GPL included in 14 | * the packaging of this file. Please review the following information 15 | * to ensure GNU General Public Licensing requirements will be met: 16 | * http://www.fsf.org/licensing/licenses/info/GPLv2.html and 17 | * http://www.gnu.org/copyleft/gpl.html. 18 | */ 19 | 20 | #include "VlHoverHandler.h" 21 | #include "VlModelManager.h" 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | using namespace Vl; 35 | 36 | VerilogHoverHandler::VerilogHoverHandler() 37 | { 38 | 39 | } 40 | 41 | static inline bool isCond( Directive di ) 42 | { 43 | return di == Cd_ifdef || di == Cd_ifndef || di == Cd_elsif || di == Cd_undef; 44 | } 45 | 46 | static inline QByteArray escape( QByteArray str ) 47 | { 48 | return str.trimmed(); 49 | } 50 | 51 | static QString prettyPrint( const PpSymbols::Define& d ) 52 | { 53 | QString str; 54 | QTextStream out( &str, QIODevice::WriteOnly ); 55 | 56 | out << "`define " << d.d_name; 57 | if( !d.d_args.isEmpty() ) 58 | { 59 | out << "( "; 60 | out << d.d_args.join(", "); 61 | out << " ) "; 62 | }else 63 | out << " "; 64 | 65 | foreach( const Token& t, d.d_toks ) 66 | { 67 | if( t.d_type < TT_Specials ) 68 | out << t.getName(); 69 | else if( t.d_type == Tok_Str ) 70 | out << "\"" << escape(t.d_val) << "\""; 71 | else if( t.d_type == Tok_SysName ) 72 | out << "$" << t.d_val; 73 | else 74 | out << t.d_val; 75 | out << " "; 76 | } 77 | 78 | return str; 79 | } 80 | 81 | void VerilogHoverHandler::identifyMatch(TextEditor::TextEditorWidget* editorWidget, int pos) 82 | { 83 | QString text = editorWidget->extraSelectionTooltip(pos); 84 | 85 | if( !text.isEmpty() ) 86 | { 87 | setToolTip(text); 88 | return; 89 | } 90 | // else 91 | 92 | QTextCursor cur(editorWidget->document()); 93 | cur.setPosition(pos); 94 | 95 | const QString file = editorWidget->textDocument()->filePath().toString(); 96 | CrossRefModel* mdl = ModelManager::instance()->getModelForCurrentProjectOrDirPath(file); 97 | 98 | const int line = cur.blockNumber() + 1; 99 | const int col = cur.columnNumber() + 1; 100 | 101 | int tokPos; 102 | QList toks = CrossRefModel::findTokenByPos( cur.block().text(), col, &tokPos, 103 | mdl->getFcache()->supportSvExt(file) ); 104 | if( tokPos != -1 ) 105 | { 106 | const Token& t = toks[tokPos]; 107 | if( t.d_type == Tok_CoDi && matchDirective(t.d_val) == Cd_Invalid ) 108 | { 109 | PpSymbols::Define d = mdl->getSyms()->getSymbol( t.d_val ); 110 | if( !d.d_name.isEmpty() ) 111 | setToolTip( prettyPrint(d) ); 112 | }else if( t.d_type == Tok_Str && tokPos > 0 && toks[tokPos-1].d_type == Tok_CoDi && 113 | matchDirective(toks[tokPos-1].d_val) == Cd_include ) 114 | { 115 | const QString path = mdl->getIncs()->findPath( t.d_val, file ); 116 | if( !path.isEmpty() ) 117 | setToolTip( path ); 118 | }else if( t.d_type == Tok_Ident && tokPos > 0 && toks[tokPos-1].d_type == Tok_CoDi && 119 | isCond( matchDirective( toks[tokPos-1].d_val) ) ) 120 | { 121 | PpSymbols::Define d = mdl->getSyms()->getSymbol( t.d_val ); 122 | if( !d.d_name.isEmpty() ) 123 | setToolTip( prettyPrint(d) ); 124 | }else if( t.d_type == Tok_Ident ) 125 | { 126 | CrossRefModel::TreePath path = mdl->findSymbolBySourcePos( file, line, col ); 127 | if( path.isEmpty() ) 128 | return; 129 | CrossRefModel::IdentDeclRef decl = mdl->findDeclarationOfSymbol(path.first().data()); 130 | if( decl.data() == 0 ) 131 | return; 132 | // qDebug() << "declared" << decl->decl()->tok().d_sourcePath << decl->decl()->tok().d_lineNr; 133 | FileCache* fcache = ModelManager::instance()->getFileCache(); 134 | const QByteArray line = fcache->fetchTextLineFromFile( 135 | decl->decl()->tok().d_sourcePath, decl->decl()->tok().d_lineNr ); 136 | QTextStream out(&text); 137 | QStringList parts = CrossRefModel::qualifiedNameParts(path,true); 138 | for( int l = 0; l < parts.size(); l++ ) 139 | { 140 | if( l != 0 ) 141 | out << endl << QString(l*3,QChar(' ')) << QChar('.'); 142 | out << parts[l]; 143 | } 144 | int len = decl->decl()->tok().d_len; 145 | if( len == 0 ) 146 | len = -1; 147 | // TODO: für Ports in alter Delkaration nicht optimal 148 | out << endl << QString::fromLatin1(line.mid(decl->decl()->tok().d_colNr-1,len).simplified()) 149 | << " " << QString::fromLatin1(decl->tok().d_val); 150 | if( decl->decl()->tok().d_sourcePath != file ) 151 | out << endl << tr("declared in ") << QFileInfo(decl->decl()->tok().d_sourcePath).fileName(); 152 | setToolTip( text ); 153 | // NOTE: mit html funktioniert es nicht! 154 | } 155 | } 156 | } 157 | 158 | -------------------------------------------------------------------------------- /VlIcarusConfiguration.h: -------------------------------------------------------------------------------- 1 | #ifndef VLICARUSCONFIGURATION_H 2 | #define VLICARUSCONFIGURATION_H 3 | 4 | /* 5 | * Copyright 2018 Rochus Keller 6 | * 7 | * This file is part of the VerilogCreator plugin. 8 | * 9 | * The following is the license that applies to this copy of the 10 | * plugin. For a license to use the plugin under conditions 11 | * other than those described here, please email to me@rochus-keller.ch. 12 | * 13 | * GNU General Public License Usage 14 | * This file may be used under the terms of the GNU General Public 15 | * License (GPL) versions 2.0 or 3.0 as published by the Free Software 16 | * Foundation and appearing in the file LICENSE.GPL included in 17 | * the packaging of this file. Please review the following information 18 | * to ensure GNU General Public Licensing requirements will be met: 19 | * http://www.fsf.org/licensing/licenses/info/GPLv2.html and 20 | * http://www.gnu.org/copyleft/gpl.html. 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | class QLabel; 30 | class QCheckBox; 31 | 32 | namespace Vl 33 | { 34 | class IcarusBuildConfig : public ProjectExplorer::BuildConfiguration 35 | { 36 | Q_OBJECT 37 | public: 38 | static const char* ID; 39 | 40 | explicit IcarusBuildConfig(ProjectExplorer::Target *parent); 41 | 42 | ProjectExplorer::NamedWidget* createConfigWidget(); 43 | BuildType buildType() const; 44 | 45 | static ProjectExplorer::BuildConfiguration* create( ProjectExplorer::Target* parent, 46 | const ProjectExplorer::BuildInfo* info ); 47 | 48 | protected: 49 | IcarusBuildConfig(ProjectExplorer::Target *parent, Core::Id id); 50 | IcarusBuildConfig(ProjectExplorer::Target *parent, IcarusBuildConfig *source); 51 | friend class BuildConfigurationFactory; 52 | friend class IcarusBuildConfigWidget; 53 | }; 54 | 55 | class IcarusBuildConfigWidget : public ProjectExplorer::NamedWidget 56 | { 57 | Q_OBJECT 58 | 59 | public: 60 | IcarusBuildConfigWidget(IcarusBuildConfig *bc); 61 | protected slots: 62 | void buildDirectoryChanged(); 63 | void environmentChanged(); 64 | private: 65 | Utils::PathChooser* d_buildPath; 66 | IcarusBuildConfig* d_conf; 67 | }; 68 | 69 | class IcarusMakeStep : public ProjectExplorer::AbstractProcessStep 70 | { 71 | Q_OBJECT 72 | public: 73 | static const char* ID; 74 | 75 | explicit IcarusMakeStep(ProjectExplorer::BuildStepList *parent); 76 | 77 | bool init(); 78 | void run(QFutureInterface &fi); 79 | bool immutable() const { return false; } 80 | ProjectExplorer::BuildStepConfigWidget* createConfigWidget(); 81 | QVariantMap toMap() const; 82 | protected: 83 | QString makeCommand(const Utils::Environment &environment) const; 84 | bool fromMap(const QVariantMap &map); 85 | private: 86 | QString d_cmd; 87 | QString d_args; 88 | friend class IcarusMakeStepWidget; 89 | }; 90 | 91 | class IcarusMakeStepWidget : public ProjectExplorer::BuildStepConfigWidget 92 | { 93 | Q_OBJECT 94 | 95 | public: 96 | IcarusMakeStepWidget(IcarusMakeStep *makeStep); 97 | QString displayName() const; 98 | QString summaryText() const; 99 | 100 | private slots: 101 | void makeLineEditTextEdited(); 102 | void makeArgumentsLineEditTextEdited(); 103 | void updateMakeOverrrideLabel(); 104 | void updateDetails(); 105 | 106 | private: 107 | IcarusMakeStep* d_step; 108 | QString d_summary; 109 | QLabel* d_cmdLabel; 110 | QLineEdit* d_cmd; 111 | QLineEdit* d_args; 112 | }; 113 | 114 | class IcarusCleanStep : public ProjectExplorer::AbstractProcessStep 115 | { 116 | Q_OBJECT 117 | public: 118 | static const char* ID; 119 | 120 | explicit IcarusCleanStep(ProjectExplorer::BuildStepList *parent); 121 | 122 | bool init(); 123 | void run(QFutureInterface &fi); 124 | bool immutable() const { return true; } 125 | ProjectExplorer::BuildStepConfigWidget* createConfigWidget(); 126 | }; 127 | 128 | class IcarusCleanStepWidget : public ProjectExplorer::BuildStepConfigWidget 129 | { 130 | Q_OBJECT 131 | 132 | public: 133 | IcarusCleanStepWidget(IcarusCleanStep *makeStep); 134 | QString displayName() const; 135 | QString summaryText() const; 136 | }; 137 | 138 | class IcarusRunConfiguration : public ProjectExplorer::LocalApplicationRunConfiguration 139 | { 140 | Q_OBJECT 141 | public: 142 | static const char* ID; 143 | static const char* Name; 144 | 145 | virtual QWidget* createConfigurationWidget(); 146 | virtual QString executable() const; 147 | virtual ProjectExplorer::ApplicationLauncher::Mode runMode() const; 148 | virtual QString workingDirectory() const; 149 | virtual QString commandLineArguments() const; 150 | virtual void addToBaseEnvironment(Utils::Environment &env) const; 151 | QVariantMap toMap() const; 152 | 153 | protected: 154 | explicit IcarusRunConfiguration(ProjectExplorer::Target *target); 155 | explicit IcarusRunConfiguration(ProjectExplorer::Target *target, IcarusRunConfiguration *rc); 156 | virtual bool fromMap(const QVariantMap &map); 157 | friend class RunConfigurationFactory; 158 | friend class IcarusRunConfigWidget; 159 | private: 160 | QString d_cmd; 161 | bool d_terminal; 162 | }; 163 | 164 | class IcarusRunConfigWidget : public QWidget 165 | { 166 | Q_OBJECT 167 | public: 168 | IcarusRunConfigWidget( IcarusRunConfiguration* ); 169 | private slots: 170 | void cmdEdited(); 171 | void termChanged(); 172 | private: 173 | IcarusRunConfiguration* d_cfg; 174 | QLineEdit* d_cmd; 175 | QCheckBox* d_term; 176 | }; 177 | } 178 | 179 | #endif // VLICARUSCONFIGURATION_H 180 | -------------------------------------------------------------------------------- /VlProjectEditor.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Rochus Keller 3 | * 4 | * This file is part of the VerilogCreator plugin. 5 | * 6 | * The following is the license that applies to this copy of the 7 | * plugin. For a license to use the plugin under conditions 8 | * other than those described here, please email to me@rochus-keller.ch. 9 | * 10 | * GNU General Public License Usage 11 | * This file may be used under the terms of the GNU General Public 12 | * License (GPL) versions 2.0 or 3.0 as published by the Free Software 13 | * Foundation and appearing in the file LICENSE.GPL included in 14 | * the packaging of this file. Please review the following information 15 | * to ensure GNU General Public Licensing requirements will be met: 16 | * http://www.fsf.org/licensing/licenses/info/GPLv2.html and 17 | * http://www.gnu.org/copyleft/gpl.html. 18 | */ 19 | 20 | #include "VlProjectEditor.h" 21 | #include "VlConstants.h" 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | using namespace Vl; 31 | using namespace TextEditor; 32 | 33 | Editor2::Editor2() 34 | { 35 | addContext(Constants::LangQmake); 36 | } 37 | 38 | EditorFactory2::EditorFactory2() 39 | { 40 | setId(Constants::EditorId2); 41 | setDisplayName(qApp->translate("OpenWith::Editors", Constants::EditorDisplayName2)); 42 | addMimeType(Constants::ProjectMimeType); 43 | 44 | setDocumentCreator([]() { return new EditorDocument2; }); 45 | // setIndenterCreator([]() { return new Indenter; }); 46 | setEditorWidgetCreator([]() { return new EditorWidget2; }); 47 | setEditorCreator([]() { return new Editor2; }); 48 | //setAutoCompleterCreator([]() { return new AutoCompleter; }); 49 | //setCompletionAssistProvider(new CompletionAssistProvider); 50 | 51 | QStringList vars; 52 | vars << "INCDIRS" << "DEFINES" << "LIBDIRS" << "LIBFILES" << "LIBEXT" << "OTHER_FILES" 53 | << "SRCDIRS" << "SRCFILES" << "SRCEXT" << "CONFIG" << "TOPMOD" 54 | << "BUILD_UNDEFS" << "VLTR_UNDEFS" << "VLTR_ARGS" << "YOSYS_UNDEFS" << "YOSYS_CMDS"; 55 | vars.sort(); 56 | QStringList funcs; 57 | funcs << "member" << "first" << "last" << "cat" << "fromfile" << "eval" << "list" << "sprintf" 58 | << "join" << "split" << "basename" << "dirname" << "section" << "find" << "system" 59 | << "unique" << "quote" << "escape_expand" << "upper" << "lower" << "re_escape" 60 | << "files" << "prompt" << "replace" << "requires" << "greaterThan" << "lessThan" 61 | << "equals" << "isEqual" << "exists" << "export" << "clear" << "unset" << "eval" 62 | << "CONFIG" << "if" << "isActiveConfig" << "system" << "return" << "break" 63 | << "next" << "defined" << "contains" << "infile" << "count" << "isEmpty" 64 | << "include" << "load" << "debug" << "error" << "message" << "warning"; 65 | funcs.sort(); 66 | 67 | TextEditor::Keywords keywords( vars, funcs , QMap() ); 68 | setSyntaxHighlighterCreator([keywords]() { return new Highlighter2(keywords); }); 69 | setCommentStyle(Utils::CommentDefinition::HashStyle); 70 | setParenthesesMatchingEnabled(true); 71 | setCodeFoldingSupported(true); 72 | setMarksVisible(true); 73 | //addHoverHandler(new HoverHandler); 74 | 75 | setEditorActionHandlers(TextEditor::TextEditorActionHandler::Format 76 | | TextEditor::TextEditorActionHandler::UnCommentSelection 77 | | TextEditor::TextEditorActionHandler::UnCollapseAll 78 | | TextEditor::TextEditorActionHandler::FollowSymbolUnderCursor 79 | ); 80 | } 81 | 82 | EditorDocument2::EditorDocument2() 83 | { 84 | setId(Constants::EditorId2); 85 | } 86 | 87 | EditorWidget2::EditorWidget2() 88 | { 89 | 90 | } 91 | 92 | void EditorWidget2::contextMenuEvent(QContextMenuEvent* e) 93 | { 94 | QPointer menu(new QMenu(this)); 95 | 96 | Core::ActionContainer *mcontext = Core::ActionManager::actionContainer(Vl::Constants::EditorContextMenuId2); 97 | QMenu *contextMenu = mcontext->menu(); 98 | 99 | foreach (QAction *action, contextMenu->actions()) { 100 | menu->addAction(action); 101 | } 102 | 103 | appendStandardContextMenuActions(menu); 104 | 105 | menu->exec(e->globalPos()); 106 | if (!menu) 107 | return; 108 | delete menu; 109 | } 110 | 111 | static std::pair make(int i,TextEditor::TextStyle s){ 112 | return std::pair(i,s);} 113 | 114 | Highlighter2::Highlighter2(const Keywords& keywords):m_keywords(keywords) 115 | { 116 | static QVector categories; 117 | categories << C_TYPE << C_KEYWORD << C_COMMENT << C_VISUAL_WHITESPACE; 118 | setTextFormatCategories(categories); 119 | } 120 | 121 | void Highlighter2::highlightBlock(const QString& text) 122 | { 123 | if (text.isEmpty()) 124 | return; 125 | 126 | QString buf; 127 | bool inCommentMode = false; 128 | 129 | QTextCharFormat emptyFormat; 130 | int i = 0; 131 | for (;;) { 132 | const QChar c = text.at(i); 133 | if (inCommentMode) { 134 | setFormat(i, 1, formatForCategory(ProfileCommentFormat)); 135 | } else { 136 | if (c.isLetter() || c == QLatin1Char('_') || c == QLatin1Char('.') || c.isDigit()) { 137 | buf += c; 138 | setFormat(i - buf.length()+1, buf.length(), emptyFormat); 139 | if (!buf.isEmpty() && m_keywords.isFunction(buf)) 140 | setFormat(i - buf.length()+1, buf.length(), formatForCategory(ProfileFunctionFormat)); 141 | else if (!buf.isEmpty() && m_keywords.isVariable(buf)) 142 | setFormat(i - buf.length()+1, buf.length(), formatForCategory(ProfileVariableFormat)); 143 | } else if (c == QLatin1Char('(')) { 144 | if (!buf.isEmpty() && m_keywords.isFunction(buf)) 145 | setFormat(i - buf.length(), buf.length(), formatForCategory(ProfileFunctionFormat)); 146 | buf.clear(); 147 | } else if (c == QLatin1Char('#')) { 148 | inCommentMode = true; 149 | setFormat(i, 1, formatForCategory(ProfileCommentFormat)); 150 | buf.clear(); 151 | } else { 152 | if (!buf.isEmpty() && m_keywords.isVariable(buf)) 153 | setFormat(i - buf.length(), buf.length(), formatForCategory(ProfileVariableFormat)); 154 | buf.clear(); 155 | } 156 | } 157 | i++; 158 | if (i >= text.length()) 159 | break; 160 | } 161 | 162 | applyFormatToSpaces(text, formatForCategory(ProfileVisualWhitespaceFormat)); 163 | } 164 | -------------------------------------------------------------------------------- /VlSdfEditor.cpp: -------------------------------------------------------------------------------- 1 | #include "VlSdfEditor.h" 2 | #include "VlConstants.h" 3 | #include "VlIndenter.h" 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | using namespace Vl; 15 | using namespace TextEditor; 16 | 17 | Editor3::Editor3() 18 | { 19 | addContext(Constants::LangSdf); 20 | } 21 | 22 | EditorFactory3::EditorFactory3() 23 | { 24 | setId(Constants::EditorId3); 25 | setDisplayName(qApp->translate("OpenWith::Editors", Constants::EditorDisplayName3)); 26 | addMimeType(Constants::SdfMimeType); 27 | 28 | setDocumentCreator([]() { return new EditorDocument3; }); 29 | //setIndenterCreator([]() { return new Indenter; }); 30 | setIndenterCreator([]() { return new VerilogIndenter; }); 31 | setEditorWidgetCreator([]() { return new EditorWidget3; }); 32 | setEditorCreator([]() { return new Editor3; }); 33 | //setAutoCompleterCreator([]() { return new AutoCompleter; }); 34 | //setCompletionAssistProvider(new CompletionAssistProvider); 35 | 36 | setSyntaxHighlighterCreator([]() { return new Highlighter3(); }); 37 | setCommentStyle(Utils::CommentDefinition::CppStyle); 38 | setParenthesesMatchingEnabled(true); 39 | setCodeFoldingSupported(true); 40 | setMarksVisible(true); 41 | //addHoverHandler(new HoverHandler); 42 | 43 | setEditorActionHandlers(TextEditor::TextEditorActionHandler::Format 44 | | TextEditor::TextEditorActionHandler::UnCommentSelection 45 | | TextEditor::TextEditorActionHandler::UnCollapseAll 46 | | TextEditor::TextEditorActionHandler::FollowSymbolUnderCursor 47 | ); 48 | } 49 | 50 | EditorDocument3::EditorDocument3() 51 | { 52 | setId(Constants::EditorId3); 53 | } 54 | 55 | 56 | void EditorWidget3::contextMenuEvent(QContextMenuEvent* e) 57 | { 58 | TextEditorWidget::contextMenuEvent(e); // TODO 59 | } 60 | 61 | 62 | Highlighter3::Highlighter3(QTextDocument* doc):SyntaxHighlighter(doc) 63 | { 64 | for( int i = 0; i < C_Max; i++ ) 65 | { 66 | d_format[i].setFontWeight(QFont::Normal); 67 | d_format[i].setForeground(Qt::black); 68 | d_format[i].setBackground(Qt::transparent); 69 | } 70 | d_format[C_Num].setForeground(QColor(0, 153, 153)); 71 | const QColor brown( 147, 39, 39 ); 72 | d_format[C_Str].setForeground(brown); // QColor(208, 16, 64)); 73 | d_format[C_Cmt].setForeground(QColor(153, 153, 136)); 74 | d_format[C_Kw].setForeground(QColor(68, 85, 136)); 75 | //d_format[C_Kw].setFontWeight(QFont::Bold); 76 | d_format[C_Op].setForeground(Qt::red); // QColor(153, 0, 0)); 77 | d_format[C_Op].setFontWeight(QFont::Bold); 78 | // d_format[C_Ident].setForeground(Qt::darkGreen); 79 | } 80 | 81 | void Highlighter3::highlightBlock(const QString& text) 82 | { 83 | const int previousBlockState_ = previousBlockState(); 84 | int lexerState = 0, initialBraceDepth = 0; 85 | if (previousBlockState_ != -1) { 86 | lexerState = previousBlockState_ & 0xff; 87 | initialBraceDepth = previousBlockState_ >> 8; 88 | } 89 | 90 | int braceDepth = initialBraceDepth; 91 | int foldingIndent = initialBraceDepth; 92 | 93 | if (TextBlockUserData *userData = TextDocumentLayout::testUserData(currentBlock())) { 94 | userData->setFoldingIndent(0); 95 | userData->setFoldingStartIncluded(false); 96 | userData->setFoldingEndIncluded(false); 97 | } 98 | 99 | int start = 0; 100 | if( lexerState == 1 ) 101 | { 102 | // wir sind in einem Multi Line Comment 103 | // suche das Ende 104 | QTextCharFormat f = formatForCategory(C_Cmt); 105 | int pos = text.indexOf("*/"); 106 | if( pos == -1 ) 107 | { 108 | // the whole block ist part of the comment 109 | setFormat( start, text.size(), f ); 110 | TextDocumentLayout::clearParentheses(currentBlock()); 111 | TextDocumentLayout::setFoldingIndent(currentBlock(), foldingIndent); 112 | setCurrentBlockState( (braceDepth << 8) | lexerState); 113 | return; 114 | }else 115 | { 116 | // End of Comment found 117 | pos += 2; 118 | setFormat( start, pos , f ); 119 | lexerState = 0; 120 | braceDepth--; 121 | start = pos; 122 | } 123 | } 124 | 125 | Parentheses parentheses; 126 | parentheses.reserve(20); 127 | 128 | Sdf::Lexer lex; 129 | lex.setIgnoreComments(false); 130 | lex.setPackComments(false); 131 | 132 | const QList tokens = lex.tokens(text.mid(start)); 133 | for( int i = 0; i < tokens.size(); ++i ) 134 | { 135 | const Sdf::Token &t = tokens.at(i); 136 | 137 | QTextCharFormat f; 138 | if( t.d_type == Sdf::Tok_Comment ) 139 | f = formatForCategory(C_Cmt); // one line comment 140 | else if( t.d_type == Sdf::Tok_Lcmt ) 141 | { 142 | braceDepth++; 143 | f = formatForCategory(C_Cmt); 144 | lexerState = 1; 145 | }else if( t.d_type == Sdf::Tok_Rcmt ) 146 | { 147 | braceDepth--; 148 | f = formatForCategory(C_Cmt); 149 | lexerState = 0; 150 | }else if( t.d_type == Sdf::Tok_Str ) 151 | f = formatForCategory(C_Str); 152 | else if( t.d_type == Sdf::Tok_Int || t.d_type == Sdf::Tok_Real ) 153 | f = formatForCategory(C_Num); 154 | else if( Sdf::tokenTypeIsLiteral(t.d_type) ) 155 | { 156 | switch( t.d_type ) 157 | { 158 | case Sdf::Tok_Lpar: 159 | ++braceDepth; 160 | parentheses.append(Parenthesis(Parenthesis::Opened, text[t.d_colNr-1], t.d_colNr-1 )); 161 | // if ( i == 0 ) 162 | // { 163 | // ++foldingIndent; 164 | // TextDocumentLayout::userData(currentBlock())->setFoldingStartIncluded(true); 165 | // } 166 | break; 167 | case Sdf::Tok_Lbrack: 168 | parentheses.append(Parenthesis(Parenthesis::Opened, text[t.d_colNr-1], t.d_colNr-1 )); 169 | break; 170 | case Sdf::Tok_Rpar: 171 | parentheses.append(Parenthesis(Parenthesis::Closed, text[t.d_colNr-1], t.d_colNr-1 )); 172 | --braceDepth; 173 | // if (braceDepth < foldingIndent) 174 | // { 175 | // // unless we are at the end of the block, we reduce the folding indent 176 | // if (i == tokens.size()-1 ) 177 | // TextDocumentLayout::userData(currentBlock())->setFoldingEndIncluded(true); 178 | // else 179 | // foldingIndent = qMin(braceDepth, foldingIndent); 180 | // } 181 | break; 182 | case Sdf::Tok_Rbrack: 183 | parentheses.append(Parenthesis(Parenthesis::Closed, text[t.d_colNr-1], t.d_colNr-1 )); 184 | break; 185 | } 186 | f = formatForCategory(C_Op); 187 | }else if( Sdf::tokenTypeIsKeyword(t.d_type) ) 188 | f = formatForCategory(C_Kw); 189 | else if( t.d_type == Sdf::Tok_Ident ) 190 | f = formatForCategory(C_Ident); 191 | 192 | if( f.isValid() ) 193 | { 194 | setFormat( t.d_colNr-1, t.d_len, f ); 195 | } 196 | } 197 | 198 | TextDocumentLayout::setParentheses(currentBlock(), parentheses); 199 | // if the block is ifdefed out, we only store the parentheses, but 200 | 201 | // do not adjust the brace depth. 202 | if (TextDocumentLayout::ifdefedOut(currentBlock())) { 203 | braceDepth = initialBraceDepth; 204 | foldingIndent = initialBraceDepth; 205 | } 206 | 207 | TextDocumentLayout::setFoldingIndent(currentBlock(), foldingIndent); 208 | setCurrentBlockState((braceDepth << 8) | lexerState ); 209 | } 210 | -------------------------------------------------------------------------------- /VlPlugin.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Rochus Keller 3 | * 4 | * This file is part of the VerilogCreator plugin. 5 | * 6 | * The following is the license that applies to this copy of the 7 | * plugin. For a license to use the plugin under conditions 8 | * other than those described here, please email to me@rochus-keller.ch. 9 | * 10 | * GNU General Public License Usage 11 | * This file may be used under the terms of the GNU General Public 12 | * License (GPL) versions 2.0 or 3.0 as published by the Free Software 13 | * Foundation and appearing in the file LICENSE.GPL included in 14 | * the packaging of this file. Please review the following information 15 | * to ensure GNU General Public Licensing requirements will be met: 16 | * http://www.fsf.org/licensing/licenses/info/GPLv2.html and 17 | * http://www.gnu.org/copyleft/gpl.html. 18 | */ 19 | 20 | #include "VlPlugin.h" 21 | #include "VlProjectManager.h" 22 | #include "VlConstants.h" 23 | #include "VlVerilogEditor.h" 24 | #include "VlProjectEditor.h" 25 | #include "VlSdfEditor.h" 26 | #include "VlModelManager.h" 27 | #include "VlConfigurationFactory.h" 28 | #include "VlProject.h" 29 | #include "VlOutlineWidget.h" 30 | #include "VlModuleLocator.h" 31 | #include "VlCompletionAssistProvider.h" 32 | #include "VlSymbolLocator.h" 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | 46 | #include 47 | #include 48 | #include 49 | #include 50 | 51 | #include 52 | #include 53 | 54 | using namespace VerilogCreator::Internal; 55 | 56 | VerilogCreatorPlugin* VerilogCreatorPlugin::d_instance = 0; 57 | 58 | // NOTE: damit *.v mit diesem Plugin assoziiert wird, muss man in QtCreator/Options/Environment die bereits 59 | // bestehende Bindung von text/x-verilog *.v löschen!!!! 60 | // Problem gelöst, indem ich hier Mime text/x-verilog verwende und bestehendes damit überschreibe. 61 | 62 | VerilogCreatorPlugin::VerilogCreatorPlugin() 63 | { 64 | d_instance = this; 65 | } 66 | 67 | VerilogCreatorPlugin::~VerilogCreatorPlugin() 68 | { 69 | // Unregister objects from the plugin manager's object pool 70 | // Delete members 71 | 72 | d_instance = 0; 73 | } 74 | 75 | VerilogCreatorPlugin*VerilogCreatorPlugin::instance() 76 | { 77 | return d_instance; 78 | } 79 | 80 | bool VerilogCreatorPlugin::initialize(const QStringList &arguments, QString *errorString) 81 | { 82 | Q_UNUSED(errorString); 83 | Q_UNUSED(arguments); 84 | 85 | Vl::ModelManager::instance(); 86 | 87 | initializeToolsSettings(); 88 | 89 | addAutoReleasedObject(new Vl::EditorFactory1); 90 | addAutoReleasedObject(new Vl::EditorFactory2); 91 | addAutoReleasedObject(new Vl::EditorFactory3); 92 | addAutoReleasedObject(new Vl::OutlineWidgetFactory); 93 | addAutoReleasedObject(new Vl::ModuleLocator); 94 | addAutoReleasedObject(new Vl::SymbolLocator); 95 | addAutoReleasedObject(new Vl::ProjectManager); 96 | addAutoReleasedObject(new Vl::MakeStepFactory); 97 | addAutoReleasedObject(new Vl::BuildConfigurationFactory); 98 | addAutoReleasedObject(new Vl::RunConfigurationFactory); 99 | 100 | // TODO Core::IWizardFactory::registerFactoryCreator([]() { 101 | // return QList() << new ProjectWizard; 102 | // }); 103 | 104 | //addAutoReleasedObject(new ProjectWizard); 105 | 106 | Core::Context context(Vl::Constants::EditorId1); 107 | Core::ActionContainer *contextMenu1 = Core::ActionManager::createMenu(Vl::Constants::EditorContextMenuId1); 108 | Core::ActionContainer * contextMenu2 = Core::ActionManager::createMenu(Vl::Constants::EditorContextMenuId2); 109 | Core::Command *cmd; 110 | Core::ActionContainer * toolsMenu = Core::ActionManager::createMenu(Vl::Constants::ToolsMenuId); 111 | toolsMenu->menu()->setTitle(tr("&Verilog")); 112 | Core::ActionManager::actionContainer(Core::Constants::M_TOOLS)->addMenu(toolsMenu); 113 | 114 | 115 | cmd = Core::ActionManager::command(TextEditor::Constants::FOLLOW_SYMBOL_UNDER_CURSOR); 116 | contextMenu1->addAction(cmd); 117 | toolsMenu->addAction(cmd); 118 | 119 | d_findUsagesAction = new QAction(tr("Find Usages"), this); 120 | cmd = Core::ActionManager::registerAction(d_findUsagesAction, Vl::Constants::FindUsagesCmd, context); 121 | cmd->setKeySequence(QKeySequence(tr("Ctrl+Shift+U"))); 122 | connect(d_findUsagesAction, SIGNAL(triggered()), this, SLOT(onFindUsages())); 123 | contextMenu1->addAction(cmd); 124 | toolsMenu->addAction(cmd); 125 | 126 | d_gotoOuterBlockAction = new QAction(tr("Go to Outer Block"), this); 127 | cmd = Core::ActionManager::registerAction(d_gotoOuterBlockAction, Vl::Constants::GotoOuterBlockCmd, context); 128 | cmd->setDefaultKeySequence(QKeySequence(tr("ALT+Up"))); 129 | connect(d_gotoOuterBlockAction, SIGNAL(triggered()), this, SLOT(onGotoOuterBlock())); 130 | contextMenu1->addAction(cmd); 131 | toolsMenu->addAction(cmd); 132 | 133 | Core::Command *sep = contextMenu1->addSeparator(); 134 | 135 | cmd = Core::ActionManager::command(TextEditor::Constants::AUTO_INDENT_SELECTION); 136 | contextMenu1->addAction(cmd); 137 | contextMenu2->addAction(cmd); 138 | 139 | cmd = Core::ActionManager::command(TextEditor::Constants::UN_COMMENT_SELECTION); 140 | contextMenu1->addAction(cmd); 141 | contextMenu2->addAction(cmd); 142 | 143 | ProjectExplorer::TaskHub::addCategory(Vl::Constants::TaskId, tr("Verilog Parser")); 144 | 145 | 146 | Core::ActionContainer *mproject = Core::ActionManager::actionContainer(ProjectExplorer::Constants::M_PROJECTCONTEXT); 147 | d_reloadProject = new QAction(tr("Reload Project"), this); 148 | cmd = Core::ActionManager::registerAction(d_reloadProject, Vl::Constants::ReloadProjectCmd, 149 | Core::Context(ProjectExplorer::Constants::C_PROJECT_TREE)); 150 | connect(d_reloadProject, SIGNAL(triggered()), this, SLOT(onReloadProject())); 151 | mproject->addAction(cmd, ProjectExplorer::Constants::G_PROJECT_FILES); 152 | 153 | return true; 154 | } 155 | 156 | void VerilogCreatorPlugin::extensionsInitialized() 157 | { 158 | } 159 | 160 | ExtensionSystem::IPlugin::ShutdownFlag VerilogCreatorPlugin::aboutToShutdown() 161 | { 162 | delete Vl::ModelManager::instance(); 163 | return SynchronousShutdown; 164 | } 165 | 166 | void VerilogCreatorPlugin::onFindUsages() 167 | { 168 | if (Vl::EditorWidget1 *editorWidget = currentEditorWidget()) 169 | editorWidget->onFindUsages(); 170 | 171 | } 172 | 173 | void VerilogCreatorPlugin::onGotoOuterBlock() 174 | { 175 | if (Vl::EditorWidget1 *editorWidget = currentEditorWidget()) 176 | editorWidget->onGotoOuterBlock(); 177 | } 178 | 179 | void VerilogCreatorPlugin::onReloadProject() 180 | { 181 | Vl::Project* currentProject = dynamic_cast( ProjectExplorer::ProjectTree::currentProject() ); 182 | if( currentProject ) 183 | { 184 | currentProject->reload(); 185 | } 186 | } 187 | 188 | Vl::EditorWidget1*VerilogCreatorPlugin::currentEditorWidget() 189 | { 190 | return qobject_cast(Core::EditorManager::currentEditor()->widget()); 191 | } 192 | 193 | void VerilogCreatorPlugin::initializeToolsSettings() 194 | { 195 | Utils::MimeDatabase::addMimeTypes(QLatin1String(":/VlEditor/VlEditor.mimetypes.xml")); 196 | 197 | Utils::MimeDatabase db; 198 | //qDebug() << db.mimeTypesForFileName("test.v"); 199 | // qDebug() << "global patterns" << db.allGlobPatterns(); 200 | TextEditor::TextEditorSettings::registerMimeTypeForLanguageId(Vl::Constants::MimeType, Vl::Constants::LangVerilog); 201 | TextEditor::TextEditorSettings::registerMimeTypeForLanguageId(Vl::Constants::ProjectMimeType, Vl::Constants::LangQmake); 202 | TextEditor::TextEditorSettings::registerMimeTypeForLanguageId(Vl::Constants::SdfMimeType, Vl::Constants::LangSdf); 203 | 204 | } 205 | 206 | -------------------------------------------------------------------------------- /VlHighlighter.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Rochus Keller 3 | * 4 | * This file is part of the VerilogCreator plugin. 5 | * 6 | * The following is the license that applies to this copy of the 7 | * plugin. For a license to use the plugin under conditions 8 | * other than those described here, please email to me@rochus-keller.ch. 9 | * 10 | * GNU General Public License Usage 11 | * This file may be used under the terms of the GNU General Public 12 | * License (GPL) versions 2.0 or 3.0 as published by the Free Software 13 | * Foundation and appearing in the file LICENSE.GPL included in 14 | * the packaging of this file. Please review the following information 15 | * to ensure GNU General Public Licensing requirements will be met: 16 | * http://www.fsf.org/licensing/licenses/info/GPLv2.html and 17 | * http://www.gnu.org/copyleft/gpl.html. 18 | */ 19 | 20 | #include "VlHighlighter.h" 21 | #include "VlModelManager.h" 22 | #include 23 | #include 24 | #include 25 | using namespace Vl; 26 | using namespace TextEditor; 27 | 28 | VerilogHighlighter::VerilogHighlighter(QTextDocument* parent) : 29 | SyntaxHighlighter(parent) 30 | { 31 | for( int i = 0; i < C_Max; i++ ) 32 | { 33 | d_format[i].setFontWeight(QFont::Normal); 34 | //d_format[i].setUnderlineStyle(QTextCharFormat::NoUnderline); 35 | d_format[i].setForeground(Qt::black); 36 | d_format[i].setBackground(Qt::transparent); 37 | } 38 | d_format[C_Num].setForeground(QColor(0, 153, 153)); 39 | d_format[C_Str].setForeground(QColor(208, 16, 64)); 40 | d_format[C_Cmt].setForeground(QColor(153, 153, 136)); 41 | d_format[C_Kw].setForeground(QColor(68, 85, 136)); 42 | d_format[C_Kw].setFontWeight(QFont::Bold); 43 | d_format[C_Op].setForeground(QColor(153, 0, 0)); 44 | d_format[C_Op].setFontWeight(QFont::Bold); 45 | d_format[C_Type].setForeground(QColor(153, 0, 115)); 46 | d_format[C_Type].setFontWeight(QFont::Bold); 47 | d_format[C_Pp].setForeground(QColor(0, 134, 179)); 48 | d_format[C_Pp].setFontWeight(QFont::Bold); 49 | 50 | d_format[C_Section].setForeground(QColor(0, 128, 0)); 51 | d_format[C_Section].setBackground(QColor(230, 255, 230)); 52 | //d_format[C_Section].setFontWeight(QFont::Bold); 53 | //d_format[C_Section].setFontUnderline(true); 54 | //d_format[C_Section].setUnderlineColor(QColor(0, 200, 0)); 55 | //d_format[C_Section].setFontOverline(true); 56 | } 57 | 58 | QTextCharFormat VerilogHighlighter::formatForCategory(int c) const 59 | { 60 | return d_format[c]; 61 | } 62 | 63 | void VerilogHighlighter::highlightBlock(const QString& text) 64 | { 65 | const int previousBlockState_ = previousBlockState(); 66 | int lexerState = 0, initialBraceDepth = 0; 67 | if (previousBlockState_ != -1) { 68 | lexerState = previousBlockState_ & 0xff; 69 | initialBraceDepth = previousBlockState_ >> 8; 70 | } 71 | 72 | int braceDepth = initialBraceDepth; 73 | int foldingIndent = initialBraceDepth; 74 | 75 | if (TextBlockUserData *userData = TextDocumentLayout::testUserData(currentBlock())) { 76 | userData->setFoldingIndent(0); 77 | userData->setFoldingStartIncluded(false); 78 | userData->setFoldingEndIncluded(false); 79 | } 80 | 81 | int start = 0; 82 | if( lexerState == 1 ) 83 | { 84 | // wir sind in einem Multi Line Comment 85 | // suche das Ende 86 | QTextCharFormat f = formatForCategory(C_Cmt); 87 | f.setProperty( TokenProp, int(Tok_Comment) ); 88 | int pos = text.indexOf("*/"); 89 | if( pos == -1 ) 90 | { 91 | // the whole block ist part of the comment 92 | setFormat( start, text.size(), f ); 93 | TextDocumentLayout::clearParentheses(currentBlock()); 94 | TextDocumentLayout::setFoldingIndent(currentBlock(), foldingIndent); 95 | setCurrentBlockState( (braceDepth << 8) | lexerState); 96 | return; 97 | }else 98 | { 99 | // End of Comment found 100 | pos += 2; 101 | setFormat( start, pos , f ); 102 | lexerState = 0; 103 | braceDepth--; 104 | start = pos; 105 | } 106 | } 107 | 108 | Parentheses parentheses; 109 | parentheses.reserve(20); 110 | 111 | PpLexer lex; 112 | lex.setIgnoreAttrs(false); 113 | lex.setPackAttrs(false); 114 | lex.setIgnoreComments(false); 115 | lex.setPackComments(false); 116 | lex.setSendMacroUsage(true); 117 | if( ModelManager::instance()->getLastUsed() ) 118 | lex.setCache( ModelManager::instance()->getLastUsed()->getFcache() ); 119 | 120 | const QList tokens = lex.tokens(text.mid(start)); 121 | for( int i = 0; i < tokens.size(); ++i ) 122 | { 123 | const Token &t = tokens.at(i); 124 | 125 | if( t.d_substituted ) 126 | continue; 127 | 128 | QTextCharFormat f; 129 | if( t.d_type == Tok_Comment ) 130 | f = formatForCategory(C_Cmt); // one line comment 131 | else if( t.d_type == Tok_Section ) 132 | { 133 | braceDepth++; 134 | f = formatForCategory(C_Section); 135 | //f.setFontOverline(true); 136 | // setExtraAdditionalFormats funktioniert nicht 137 | }else if( t.d_type == Tok_SectionEnd ) 138 | { 139 | braceDepth--; 140 | f = formatForCategory(C_Section); 141 | // f.setFontUnderline(true); 142 | }else if( t.d_type == Tok_Lcmt ) 143 | { 144 | braceDepth++; 145 | f = formatForCategory(C_Cmt); 146 | lexerState = 1; 147 | }else if( t.d_type == Tok_Rcmt ) 148 | { 149 | braceDepth--; 150 | f = formatForCategory(C_Cmt); 151 | lexerState = 0; 152 | }else if( t.d_type == Tok_Str ) 153 | f = formatForCategory(C_Str); 154 | else if( tokenIsNumber(t.d_type) ) 155 | f = formatForCategory(C_Num); 156 | else if( tokenIsDelimiter(t.d_type) ) 157 | { 158 | switch( t.d_type ) 159 | { 160 | case Tok_Lpar: 161 | case Tok_Lbrack: 162 | case Tok_Lbrace: 163 | //case Tok_Latt: 164 | parentheses.append(Parenthesis(Parenthesis::Opened, text[t.d_colNr-1], t.d_colNr-1 )); 165 | break; 166 | case Tok_Rpar: 167 | case Tok_Rbrack: 168 | case Tok_Rbrace: 169 | //case Tok_Ratt: 170 | parentheses.append(Parenthesis(Parenthesis::Closed, text[t.d_colNr-1], t.d_colNr-1 )); 171 | break; 172 | } 173 | if( t.d_type == Tok_LineCont ) 174 | f = formatForCategory(C_Pp); 175 | else 176 | //if( tokenIsOperator(t.d_type) ) 177 | f = formatForCategory(C_Op); 178 | // else if( tokenIsBracket(t.d_type) ) 179 | // f = formatForCategory(C_Brack); 180 | }else if( tokenIsReservedWord(t.d_type) ) 181 | { 182 | if( tokenIsBlockBegin(t.d_type) ) 183 | { 184 | parentheses.append(Parenthesis(Parenthesis::Opened, text[t.d_colNr-1], t.d_colNr-1 )); 185 | ++braceDepth; 186 | // if a folding block opens at the beginning of a line, treat the entire line 187 | // as if it were inside the folding block 188 | if ( i == 0 && ( t.d_type == Tok_begin || t.d_type == Tok_fork ) ) 189 | { 190 | ++foldingIndent; 191 | TextDocumentLayout::userData(currentBlock())->setFoldingStartIncluded(true); 192 | } 193 | }else if( tokenIsBlockEnd(t.d_type) ) 194 | { 195 | const int pos = t.d_colNr-1 + ::strlen(tokenToString(t.d_type))-1; 196 | parentheses.append(Parenthesis(Parenthesis::Closed, text[pos], pos )); 197 | --braceDepth; 198 | if (braceDepth < foldingIndent) { 199 | // unless we are at the end of the block, we reduce the folding indent 200 | if (i == tokens.size()-1 || tokens.at(i+1).d_type == Tok_Semi ) 201 | TextDocumentLayout::userData(currentBlock())->setFoldingEndIncluded(true); 202 | else 203 | foldingIndent = qMin(braceDepth, foldingIndent); 204 | } 205 | } 206 | if( tokenIsType(t.d_type) ) 207 | f = formatForCategory(C_Type); 208 | else 209 | f = formatForCategory(C_Kw); 210 | }else if( t.d_type == Tok_Ident ) 211 | f = formatForCategory(C_Ident); 212 | else if( t.d_type == Tok_SysName ) 213 | f = formatForCategory(C_Kw); 214 | else if( t.d_type == Tok_CoDi ) 215 | { 216 | Directive di = matchDirective(t.d_val); 217 | switch(di) 218 | { 219 | case Cd_ifdef: 220 | case Cd_ifndef: 221 | braceDepth++; 222 | break; 223 | case Cd_else: 224 | case Cd_elsif: 225 | foldingIndent--; 226 | break; 227 | case Cd_endif: 228 | braceDepth--; 229 | break; 230 | default: 231 | break; 232 | } 233 | 234 | f = formatForCategory(C_Pp); 235 | } 236 | 237 | if( f.isValid() ) 238 | { 239 | f.setProperty( TokenProp, int(t.d_type) ); 240 | setFormat( t.d_colNr-1, t.d_len, f ); 241 | } 242 | } 243 | 244 | TextDocumentLayout::setParentheses(currentBlock(), parentheses); 245 | // if the block is ifdefed out, we only store the parentheses, but 246 | 247 | // do not adjust the brace depth. 248 | if (TextDocumentLayout::ifdefedOut(currentBlock())) { 249 | braceDepth = initialBraceDepth; 250 | foldingIndent = initialBraceDepth; 251 | } 252 | 253 | TextDocumentLayout::setFoldingIndent(currentBlock(), foldingIndent); 254 | setCurrentBlockState((braceDepth << 8) | lexerState ); 255 | } 256 | 257 | 258 | 259 | -------------------------------------------------------------------------------- /VlProject.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Rochus Keller 3 | * 4 | * This file is part of the VerilogCreator plugin. 5 | * 6 | * The following is the license that applies to this copy of the 7 | * plugin. For a license to use the plugin under conditions 8 | * other than those described here, please email to me@rochus-keller.ch. 9 | * 10 | * GNU General Public License Usage 11 | * This file may be used under the terms of the GNU General Public 12 | * License (GPL) versions 2.0 or 3.0 as published by the Free Software 13 | * Foundation and appearing in the file LICENSE.GPL included in 14 | * the packaging of this file. Please review the following information 15 | * to ensure GNU General Public Licensing requirements will be met: 16 | * http://www.fsf.org/licensing/licenses/info/GPLv2.html and 17 | * http://www.gnu.org/copyleft/gpl.html. 18 | */ 19 | 20 | #include "VlProject.h" 21 | #include "VlProjectManager.h" 22 | #include "VlModelManager.h" 23 | #include 24 | #include "VlConstants.h" 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | 38 | namespace Vl 39 | { 40 | class ProjectNode : public ProjectExplorer::ProjectNode 41 | { 42 | public: 43 | ProjectNode(const Utils::FileName &projectFilePath) 44 | : ProjectExplorer::ProjectNode(projectFilePath) 45 | { 46 | } 47 | 48 | QList supportedActions(Node *) const Q_DECL_OVERRIDE 49 | { return QList(); } 50 | 51 | bool canAddSubProject(const QString &) const Q_DECL_OVERRIDE { return false; } 52 | 53 | bool addSubProjects(const QStringList &) Q_DECL_OVERRIDE { return false; } 54 | 55 | bool removeSubProjects(const QStringList &) Q_DECL_OVERRIDE { return false; } 56 | 57 | bool addFiles(const QStringList &, QStringList*) Q_DECL_OVERRIDE { return false; } 58 | bool removeFiles(const QStringList &, QStringList*) Q_DECL_OVERRIDE { return false; } 59 | bool deleteFiles(const QStringList &) Q_DECL_OVERRIDE { return false; } 60 | bool renameFile(const QString &, const QString &) Q_DECL_OVERRIDE { return false; } 61 | }; 62 | } 63 | using namespace Vl; 64 | 65 | const char* Project::ID = "VerilogCreator.Project"; 66 | 67 | Project::Project(ProjectManager* projectManager, const QString& fileName): 68 | d_projectManager(projectManager),d_root(0) 69 | { 70 | setId(ID); 71 | setProjectContext(Core::Context("VerilogCreator.ProjectContext")); 72 | setProjectLanguages(Core::Context(Constants::LangVerilog)); 73 | 74 | d_document = new TextEditor::TextDocument(); 75 | d_document->setFilePath(Utils::FileName::fromString(fileName)); 76 | d_name = QFileInfo(fileName).baseName(); 77 | d_root = new ProjectNode(Utils::FileName::fromString(fileName)); 78 | d_root->setDisplayName(d_name); 79 | loadProject(fileName); 80 | d_watcher.addPath(fileName); 81 | connect( &d_watcher, SIGNAL(fileChanged(QString)), this, SLOT(onFileChanged(QString)) ); 82 | } 83 | 84 | void Project::reload() 85 | { 86 | loadProject(d_document->filePath().toString()); 87 | } 88 | 89 | QString Project::displayName() const 90 | { 91 | return d_name; 92 | } 93 | 94 | Core::IDocument*Project::document() const 95 | { 96 | return d_document; 97 | } 98 | 99 | ProjectExplorer::IProjectManager* Project::projectManager() const 100 | { 101 | return d_projectManager; 102 | } 103 | 104 | ProjectExplorer::ProjectNode*Project::rootProjectNode() const 105 | { 106 | return d_root; 107 | } 108 | 109 | QStringList Project::files(Project::FilesMode) const 110 | { 111 | return d_config.getSrcFiles() + d_config.getLibFiles(); 112 | } 113 | 114 | void Project::loadProject(const QString& fileName) 115 | { 116 | d_root->removeFolderNodes( d_root->subFolderNodes() ); 117 | d_root->removeFileNodes( d_root->fileNodes() ); 118 | 119 | CrossRefModel* mdl = ModelManager::instance()->getModelForFile(fileName); 120 | mdl->clear(); 121 | mdl->getIncs()->clear(); 122 | mdl->getSyms()->clear(); 123 | mdl->getErrs()->clear(); 124 | 125 | d_root->addFileNodes(QList() << 126 | new ProjectExplorer::FileNode(Utils::FileName::fromString(fileName), 127 | ProjectExplorer::ProjectFileType, false ) ); 128 | 129 | ProjectExplorer::FolderNode* libsFolder = new ProjectExplorer::FolderNode(Utils::FileName::fromString("Libraries")); 130 | d_root->addFolderNodes(QList() << libsFolder); 131 | 132 | ProjectExplorer::FolderNode* sourceFolder = new ProjectExplorer::FolderNode(Utils::FileName::fromString("Sources")); 133 | d_root->addFolderNodes(QList() << sourceFolder); 134 | 135 | if( !d_config.loadFromFile(fileName) ) 136 | return; // TODO: Error Message 137 | 138 | const QString oldCur = QDir::currentPath(); 139 | QDir::setCurrent(QFileInfo(fileName).path()); 140 | fillNode( d_config.getLibFiles(), libsFolder ); 141 | fillNode( d_config.getSrcFiles(), sourceFolder ); 142 | if( !d_config.getOtherFiles().isEmpty() ) 143 | { 144 | ProjectExplorer::FolderNode* othersFolder = 145 | new ProjectExplorer::FolderNode(Utils::FileName::fromString("Other Files")); 146 | d_root->addFolderNodes(QList() << othersFolder); 147 | fillNode( d_config.getOtherFiles(), othersFolder ); 148 | } 149 | QDir::setCurrent(oldCur); 150 | 151 | d_config.setup( mdl ); 152 | 153 | Utils::MimeDatabase db; 154 | Utils::MimeType mt = db.mimeTypeForName(Constants::MimeType); 155 | // qDebug() << "MimeType pre" << mt.name() << mt.suffixes() << mt.globPatterns(); 156 | QStringList pat = d_config.getConfig("SRCEXT"); 157 | pat += d_config.getConfig("LIBEXT"); 158 | pat += d_config.getConfig("SVEXT"); 159 | for( int i = 0; i < pat.size(); i++ ) 160 | pat[i] = QLatin1String("*") + pat[i]; 161 | pat += mt.globPatterns(); 162 | Utils::MimeDatabase::setGlobPatternsForMimeType( mt, pat.toSet().toList() ); 163 | // qDebug() << "MimeType post" << mt.name() << mt.suffixes() << mt.globPatterns(); 164 | 165 | emit fileListChanged(); 166 | } 167 | 168 | void Project::fillNode(const QStringList& files, ProjectExplorer::FolderNode* root) 169 | { 170 | int i = 0; 171 | QString path; 172 | ProjectExplorer::FolderNode* cur = root; 173 | while( i < files.size() ) 174 | { 175 | QFileInfo info(files[i]); 176 | if( info.path() != path ) 177 | { 178 | path = info.path(); 179 | if( info.dir() == QDir::current() ) 180 | cur = root; 181 | else 182 | { 183 | cur = new ProjectExplorer::FolderNode(Utils::FileName::fromString( 184 | QDir::current().relativeFilePath(path) ) ); 185 | root->addFolderNodes(QList() << cur ); 186 | 187 | } 188 | } 189 | cur->addFileNodes(QList() << 190 | new ProjectExplorer::FileNode(Utils::FileName::fromString(files[i]), 191 | ProjectExplorer::SourceType, false)); 192 | i++; 193 | } 194 | } 195 | 196 | ProjectExplorer::Project::RestoreResult Project::fromMap(const QVariantMap &map, QString *errorMessage) 197 | { 198 | // Diese Funktion wird von Explorer-Plugin immer aufgerufen, auch wenn .user noch nicht existiert 199 | 200 | if (ProjectExplorer::Project::fromMap(map,errorMessage) != Project::RestoreResult::Ok ) 201 | return Project::RestoreResult::Error; 202 | 203 | // aus GenericProject 204 | ProjectExplorer::Kit *defaultKit = ProjectExplorer::KitManager::defaultKit(); 205 | if ( !activeTarget() ) 206 | addTarget(createTarget(defaultKit) ); // defaultKit darf null sein, es kommt dann einfach ein Fehlertext im GUI 207 | 208 | // Sanity check: We need both a buildconfiguration and a runconfiguration! 209 | QList targetList = targets(); 210 | foreach (ProjectExplorer::Target *t, targetList) { 211 | if (!t->activeBuildConfiguration()) { 212 | // see ProjectExplorer::BuildConfiguration und IBuildConfigurationFactory 213 | // see also BuildStep und AbstractProcessStep 214 | // Beispiele in GenericBuildConfiguration bzw. andere Klassen im GenericProjectManagerPlugin 215 | // see DefaultDeployConfiguration, LocalApplicationRunConfiguration 216 | 217 | //removeTarget(t); 218 | //continue; 219 | qWarning() << "Target" << t->displayName() << "has no build configuration"; 220 | } 221 | // see DeployConfiguration 222 | if (!t->activeRunConfiguration()) 223 | // see ProjectExplorer::RunConfiguration and subclasses! 224 | qWarning() << "Target" << t->displayName() << "has no run configuration"; 225 | /* es wird automatisch QtSupport::CustomExecutableRunConfiguration gesetzt und das ist zugleich auch 226 | * die einzige verfügbare RunConfiguration 227 | else 228 | qDebug() << "Run Configuration:" << t->activeRunConfiguration()->metaObject()->className(); 229 | QList rcFactories = 230 | ProjectExplorer::IRunConfigurationFactory::find(activeTarget()); 231 | foreach( ProjectExplorer::IRunConfigurationFactory * r, rcFactories ) 232 | qDebug() << "Found" << r->metaObject()->className(); 233 | */ 234 | } 235 | 236 | // refresh(Everything); 237 | return Project::RestoreResult::Ok; 238 | } 239 | 240 | void Project::onFileChanged(const QString& path) 241 | { 242 | //qDebug() << "File changed" << path; 243 | const QString proPath = d_document->filePath().toString(); 244 | if( path == proPath ) 245 | { 246 | loadProject(path); 247 | d_watcher.addPath(path); 248 | } 249 | } 250 | 251 | -------------------------------------------------------------------------------- /VlCompletionAssistProvider.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Rochus Keller 3 | * 4 | * This file is part of the VerilogCreator plugin. 5 | * 6 | * The following is the license that applies to this copy of the 7 | * plugin. For a license to use the plugin under conditions 8 | * other than those described here, please email to me@rochus-keller.ch. 9 | * 10 | * GNU General Public License Usage 11 | * This file may be used under the terms of the GNU General Public 12 | * License (GPL) versions 2.0 or 3.0 as published by the Free Software 13 | * Foundation and appearing in the file LICENSE.GPL included in 14 | * the packaging of this file. Please review the following information 15 | * to ensure GNU General Public Licensing requirements will be met: 16 | * http://www.fsf.org/licensing/licenses/info/GPLv2.html and 17 | * http://www.gnu.org/copyleft/gpl.html. 18 | */ 19 | 20 | #include "VlCompletionAssistProvider.h" 21 | #include "VlConstants.h" 22 | #include "VlModelManager.h" 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | namespace Vl 38 | { 39 | class CompletionAssistProcessor : public TextEditor::IAssistProcessor 40 | { 41 | public: 42 | CompletionAssistProcessor() {} 43 | TextEditor::IAssistProposal* perform(const TextEditor::AssistInterface *ai) 44 | { 45 | m_interface.reset(ai); 46 | 47 | if (ai->reason() == TextEditor::IdleEditor) 48 | return 0; 49 | 50 | const int curPos = ai->position(); 51 | 52 | const QTextBlock block = ai->textDocument()->findBlock(curPos); 53 | const int lineNr = block.blockNumber() + 1; 54 | const int colNr = curPos - block.position() + 1; 55 | const QString seq = QChar(' ') + ai->textDocument()->findBlock(curPos).text().left(colNr-1); 56 | //const QString seq = ai->textAt(curPos, -CompletionAssistProvider::SeqLen ); 57 | const QString fileName = ai->fileName(); 58 | 59 | CrossRefModel* mdl = ModelManager::instance()->getModelForCurrentProject(); 60 | if( mdl == 0 ) 61 | return 0; 62 | 63 | const int prefixPos = CompletionAssistProvider::checkSequence(seq,0); 64 | if( prefixPos > 0 ) 65 | return 0; 66 | 67 | enum { PlainIdent, MacroUse, DotExpand } what = PlainIdent; 68 | if( seq.size() + prefixPos - 1 >= 0 ) 69 | { 70 | switch( seq[ seq.size() + prefixPos - 1 ].toLatin1() ) 71 | { 72 | case '.': 73 | what = DotExpand; 74 | break; 75 | case '`': 76 | what = MacroUse; 77 | break; 78 | } 79 | } 80 | //const QString prefix = seq.right(-prefixPos); 81 | //qDebug() << prefix << what << seq; 82 | 83 | QList proposals; 84 | 85 | if( what == MacroUse ) 86 | { 87 | const QByteArrayList names = mdl->getSyms()->getNames(); 88 | for( auto i = names.begin(); i != names.end(); ++i ) 89 | { 90 | auto proposal = new TextEditor::AssistProposalItem(); 91 | proposal->setText(QString::fromLatin1((*i))); 92 | //proposal->setIcon(icon); 93 | //proposal->setOrder(order); 94 | proposals << proposal; 95 | 96 | } 97 | 98 | }else // PlainIdent or DotExpand 99 | { 100 | CrossRefModel::TreePath p = mdl->findSymbolBySourcePos( fileName, lineNr, colNr, false, true ); 101 | if( p.isEmpty() ) 102 | return 0; 103 | 104 | // foreach( const CrossRefModel::SymRef& sym, p ) 105 | // qDebug() << SynTree::rToStr( sym->tok().d_type ) << sym->tok().d_lineNr << sym->tok().d_colNr; 106 | // if( p.size() > 1 ) 107 | // { 108 | // CrossRefModel::dump(p[1].constData(), 0, false); 109 | // CrossRefModel::dump(p[0].constData(), 1, false); 110 | // //qDebug() << SynTree::rToStr( p[0]->tok().d_type ) << p[0]->tok().d_lineNr << p[0]->tok().d_colNr; 111 | // } 112 | // if( !p.isEmpty() ) 113 | // CrossRefModel::dump(p.first().constData(), 0, true); 114 | 115 | CrossRefModel::Scope::Names2 names; 116 | 117 | if( what == DotExpand ) 118 | { 119 | CrossRefModel::ScopeRef module; 120 | const CrossRefModel::Branch* branch = CrossRefModel::closestBranch(p); 121 | if( branch && branch->tok().d_type == SynTree::R_module_or_udp_instantiation_ ) 122 | { 123 | CrossRefModel::SymRef sym = mdl->findGlobal(branch->tok().d_val); 124 | if( sym.constData() ) 125 | module = sym->toScope(); 126 | }else if( branch && branch->tok().d_type == SynTree::R_module_or_udp_instance_ ) 127 | { 128 | CrossRefModel::SymRef sym = mdl->findGlobal(branch->super()->tok().d_val); 129 | if( sym.constData() ) 130 | module = sym->toScope(); 131 | } 132 | if( module.constData() ) 133 | { 134 | //qDebug() << "fetching symbols of" << module->tok().d_val; 135 | names = module->getNames2(false); 136 | } 137 | 138 | }else // PlainIdent 139 | { 140 | CrossRefModel::ScopeRef scope( CrossRefModel::closestScope(p) ); 141 | if( scope.constData() ) 142 | { 143 | //qDebug() << "fetching symbols of" << scope->tok().d_val; 144 | names = scope->getNames2(); 145 | } 146 | } 147 | 148 | QPixmap iMod(":/verilogcreator/images/block.png"); 149 | QPixmap iVar(":/verilogcreator/images/var.png"); 150 | QPixmap iFunc(":/verilogcreator/images/func.png"); 151 | 152 | for( auto i = names.begin(); i != names.end(); ++i ) 153 | { 154 | auto proposal = new TextEditor::AssistProposalItem(); 155 | proposal->setText(QString::fromLatin1(i.key())); 156 | const int declType = i.value()->decl()->tok().d_type; 157 | proposal->setDetail( SynTree::rToStr( declType ) ); 158 | QPixmap icon; 159 | switch(declType) 160 | { 161 | case SynTree::R_module_declaration: 162 | case SynTree::R_udp_declaration: 163 | icon = iMod; 164 | break; 165 | case SynTree::R_task_declaration: 166 | case SynTree::R_function_declaration: 167 | icon = iFunc; 168 | break; 169 | default: 170 | icon = iVar; 171 | break; 172 | } 173 | proposal->setIcon(icon); 174 | //proposal->setOrder(order); 175 | proposals << proposal; 176 | 177 | } 178 | } 179 | 180 | if( proposals.isEmpty() ) 181 | return 0; 182 | 183 | TextEditor::GenericProposalModel *model = new TextEditor::GenericProposalModel(); 184 | model->loadContent(proposals); 185 | TextEditor::IAssistProposal *proposal = new TextEditor::GenericProposal(curPos+prefixPos, model); 186 | return proposal; 187 | } 188 | private: 189 | QScopedPointer m_interface; 190 | }; 191 | } 192 | 193 | using namespace Vl; 194 | 195 | static inline bool isInIdentChar( QChar c ) 196 | { 197 | return c.isLetterOrNumber() || c == '_' || c == '$'; 198 | } 199 | 200 | static inline bool isFirstIdentChar( QChar c ) 201 | { 202 | return c.isLetter() || c == '_' || c == '$'; 203 | } 204 | 205 | int CompletionAssistProvider::checkSequence(const QString& s, int minLen ) 206 | { 207 | // returns >0 if nothing found 208 | // else returns position from s.size() leftwards, where text begins 209 | if( s.isEmpty() ) 210 | return 1; 211 | 212 | for( int off = s.size() - 1; off >= 0; off-- ) 213 | { 214 | QChar c = s[off]; 215 | if( c == '.' || c == '`' ) 216 | return off - s.size() + 1; 217 | else if( !isInIdentChar(c) ) 218 | { 219 | off++; 220 | if( ( s.size() - off ) < minLen ) 221 | break; 222 | if( off < s.size() && isFirstIdentChar( s[off] ) ) 223 | return off - s.size(); 224 | else 225 | return 0; 226 | } 227 | } 228 | return 1; 229 | // obsolet: 230 | #if 0 231 | QChar c = s[s.size() - 1]; 232 | //qDebug() << "isActivationCharSequence" << s; 233 | if( c == '.' || c == '`' ) 234 | return 0; 235 | if( s.size() < 2 ) 236 | return 1; 237 | c = s[s.size() - 2]; 238 | if( c == '.' || c == '`' ) 239 | return -1; 240 | if( s.size() < 3 ) 241 | return 1; 242 | if( isInIdentChar(c) && isInIdentChar(s[s.size()-2]) && isFirstIdentChar(s[s.size() - 3]) ) 243 | { 244 | if( s.size() < 4 || !isInIdentChar(s[s.size()-4]) ) 245 | return -3; // Start of document; actually s includes strange content when at start of document 246 | } 247 | return 1; 248 | #endif 249 | } 250 | 251 | TextEditor::IAssistProvider::RunType CompletionAssistProvider::runType() const 252 | { 253 | return TextEditor::IAssistProvider::Synchronous; 254 | } 255 | 256 | bool CompletionAssistProvider::supportsEditor(Core::Id editorId) const 257 | { 258 | return editorId == Constants::EditorId1; 259 | } 260 | 261 | TextEditor::IAssistProcessor*CompletionAssistProvider::createProcessor() const 262 | { 263 | return new CompletionAssistProcessor(); 264 | } 265 | 266 | bool CompletionAssistProvider::isActivationCharSequence(const QString& s) const 267 | { 268 | return checkSequence(s,SeqLen-1) <= 0; 269 | } 270 | 271 | bool CompletionAssistProvider::isContinuationChar(const QChar& c) const 272 | { 273 | //qDebug() << "isContinuationChar" << c; 274 | return c.isLetterOrNumber() || c == '_' || c == '$'; 275 | } 276 | -------------------------------------------------------------------------------- /VlTclEngine.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Rochus Keller 3 | * 4 | * This file is part of the VerilogCreator plugin. 5 | * 6 | * The following is the license that applies to this copy of the 7 | * plugin. For a license to use the plugin under conditions 8 | * other than those described here, please email to me@rochus-keller.ch. 9 | * 10 | * GNU General Public License Usage 11 | * This file may be used under the terms of the GNU General Public 12 | * License (GPL) versions 2.0 or 3.0 as published by the Free Software 13 | * Foundation and appearing in the file LICENSE.GPL included in 14 | * the packaging of this file. Please review the following information 15 | * to ensure GNU General Public Licensing requirements will be met: 16 | * http://www.fsf.org/licensing/licenses/info/GPLv2.html and 17 | * http://www.gnu.org/copyleft/gpl.html. 18 | */ 19 | 20 | #include "VlTclEngine.h" 21 | #include 22 | #include 23 | #include 24 | #include 25 | using namespace Vl; 26 | 27 | static TclEngine* s_inst = 0; 28 | static int s_refCount = 0; 29 | 30 | // Inspired by https://github.com/JPNaude/Qtilities/blob/master/src/Examples/TclScriptingExample/qtclconsole.cpp 31 | 32 | static int writeStdout(ClientData, CONST char * buf, int toWrite, int *errorCode); 33 | 34 | static int writeStderr(ClientData, CONST char * buf, int toWrite, int *errorCode); 35 | 36 | static int closeChannel(ClientData, Tcl_Interp *) 37 | { 38 | return EINVAL; 39 | } 40 | 41 | static Tcl_ChannelType consoleOutputChannelType = 42 | { 43 | (char*)"console1", /* const char* typeName*/ 44 | NULL, /*Tcl_ChannelTypeVersion version*/ 45 | closeChannel /*NULL*/, /*Tcl_DriverCloseProc* closeProc*/ 46 | NULL, /*Tcl_DriverInputProc* inputProc*/ 47 | writeStdout, /*Tcl_DriverOutputProc* outputProc*/ 48 | NULL, /*Tcl_DriverSeekProc* seekProc*/ 49 | NULL, /*Tcl_DriverSetOptionProc* setOptionProc*/ 50 | NULL, /*Tcl_DriverGetOptionProc* getOptionProc*/ 51 | NULL, /*Tcl_DriverWatchProc* watchProc*/ 52 | NULL, /*Tcl_DriverGetHandleProc* getHandleProc*/ 53 | NULL, /*Tcl_DriverClose2Proc* close2Proc*/ 54 | NULL, /*Tcl_DriverBlockModeProc* blockModeProc*/ 55 | NULL, /*Tcl_DriverFlushProc* flushProc*/ 56 | NULL, /*Tcl_DriverHandlerProc * handlerProc*/ 57 | NULL, /*Tcl_DriverWideSeekProc * wideSeekProc*/ 58 | NULL, /*Tcl_DriverThreadActionProc* threadActionProc*/ 59 | NULL /*Tcl_DriverTruncateProc* truncateProc*/ 60 | }; 61 | 62 | static Tcl_ChannelType consoleErrorChannelType = 63 | { 64 | (char*)"console2", /* const char* typeName*/ 65 | NULL, /*Tcl_ChannelTypeVersion version*/ 66 | closeChannel /*NULL*/, /*Tcl_DriverCloseProc* closeProc*/ 67 | NULL, /*Tcl_DriverInputProc* inputProc*/ 68 | writeStderr, /*Tcl_DriverOutputProc* outputProc*/ 69 | NULL, /*Tcl_DriverSeekProc* seekProc*/ 70 | NULL, /*Tcl_DriverSetOptionProc* setOptionProc*/ 71 | NULL, /*Tcl_DriverGetOptionProc* getOptionProc*/ 72 | NULL, /*Tcl_DriverWatchProc* watchProc*/ 73 | NULL, /*Tcl_DriverGetHandleProc* getHandleProc*/ 74 | NULL, /*Tcl_DriverClose2Proc* close2Proc*/ 75 | NULL, /*Tcl_DriverBlockModeProc* blockModeProc*/ 76 | NULL, /*Tcl_DriverFlushProc* flushProc*/ 77 | NULL, /*Tcl_DriverHandlerProc * handlerProc*/ 78 | NULL, /*Tcl_DriverWideSeekProc * wideSeekProc*/ 79 | NULL, /*Tcl_DriverThreadActionProc* threadActionProc*/ 80 | NULL /*Tcl_DriverTruncateProc* truncateProc*/ 81 | }; 82 | 83 | struct TclEngine::Imp 84 | { 85 | typedef Tcl_Interp* (*CreateInterp)(); 86 | CreateInterp d_CreateInterp; 87 | typedef void (*DeleteInterp)(Tcl_Interp *interp); 88 | DeleteInterp d_DeleteInterp; 89 | typedef int (*Eval)(Tcl_Interp *interp, const char *script); 90 | Eval d_Eval; 91 | typedef int (*EvalFile)(Tcl_Interp *interp, const char *fileName); 92 | EvalFile d_EvalFile; 93 | typedef int (*TraceVar2)(Tcl_Interp *interp, const char *part1, const char *part2, int flags, 94 | Tcl_VarTraceProc *proc, ClientData clientData); 95 | TraceVar2 d_TraceVar2; 96 | typedef Tcl_Command (*CreateObjCommand)(Tcl_Interp *interp, const char *cmdName, Tcl_ObjCmdProc *proc, 97 | ClientData clientData, Tcl_CmdDeleteProc *deleteProc); 98 | CreateObjCommand d_CreateObjCommand; 99 | typedef void (*AppendElement)(Tcl_Interp *interp, const char *element); 100 | AppendElement d_AppendElement; 101 | typedef void (*WrongNumArgs)(Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], const char *message); 102 | WrongNumArgs d_WrongNumArgs; 103 | typedef char * (*GetString)(Tcl_Obj *objPtr); 104 | GetString d_GetString; 105 | typedef void (*SetStdChannel)(Tcl_Channel channel, int type); 106 | SetStdChannel d_SetStdChannel; 107 | typedef void (*RegisterChannel)(Tcl_Interp *interp, Tcl_Channel chan); 108 | RegisterChannel d_RegisterChannel; 109 | typedef void (*SetErrno)(int err); 110 | SetErrno d_SetErrno; 111 | typedef Tcl_Channel (*CreateChannel)(const Tcl_ChannelType *typePtr, const char *chanName, ClientData instanceData, int mask); 112 | CreateChannel d_CreateChannel; 113 | typedef int (*SetChannelOption)(Tcl_Interp *interp, Tcl_Channel chan, const char *optionName, const char *newValue); 114 | SetChannelOption d_SetChannelOption; 115 | typedef char * (*GetStringResult)(Tcl_Interp *interp); 116 | GetStringResult d_GetStringResult; 117 | 118 | Imp():d_tcl(0),d_CreateInterp(0),d_DeleteInterp(0),d_Eval(0),d_EvalFile(0),d_TraceVar2(0),d_AppendElement(0), 119 | d_WrongNumArgs(0),d_GetString(0),d_SetStdChannel(0),d_RegisterChannel(0),d_SetErrno(0), 120 | d_CreateChannel(0),d_SetChannelOption(0),d_GetStringResult(0) 121 | { 122 | d_lib.setFileName("tcl"); 123 | if( !d_lib.load() ) 124 | { 125 | qCritical() << "Cannot load libtcl"; 126 | 127 | return; 128 | } 129 | d_CreateInterp = (CreateInterp)d_lib.resolve("Tcl_CreateInterp"); 130 | d_DeleteInterp = (DeleteInterp)d_lib.resolve("Tcl_DeleteInterp"); 131 | d_Eval = (Eval)d_lib.resolve("Tcl_Eval"); 132 | d_EvalFile = (EvalFile)d_lib.resolve("Tcl_EvalFile"); 133 | d_TraceVar2 = (TraceVar2)d_lib.resolve("Tcl_TraceVar2"); 134 | d_CreateObjCommand = (CreateObjCommand)d_lib.resolve("Tcl_CreateObjCommand"); 135 | d_AppendElement = (AppendElement)d_lib.resolve("Tcl_AppendElement"); 136 | d_WrongNumArgs = (WrongNumArgs)d_lib.resolve("Tcl_WrongNumArgs"); 137 | d_GetString = (GetString)d_lib.resolve("Tcl_GetString"); 138 | d_SetStdChannel = (SetStdChannel)d_lib.resolve("Tcl_SetStdChannel"); 139 | d_RegisterChannel = (RegisterChannel)d_lib.resolve("Tcl_RegisterChannel"); 140 | d_SetErrno = (SetErrno)d_lib.resolve("Tcl_SetErrno"); 141 | d_CreateChannel = (CreateChannel)d_lib.resolve("Tcl_CreateChannel"); 142 | d_SetChannelOption = (SetChannelOption)d_lib.resolve("Tcl_SetChannelOption"); 143 | d_GetStringResult = (GetStringResult)d_lib.resolve("Tcl_GetStringResult"); 144 | 145 | d_tcl = d_CreateInterp(); 146 | d_CreateObjCommand(d_tcl, "get_vlpro_var", get_vlpro_var, this, 0 ); 147 | 148 | Tcl_Channel outConsoleChannel = d_CreateChannel(&consoleOutputChannelType, "stdout", this, TCL_WRITABLE); 149 | if( outConsoleChannel ) 150 | { 151 | d_SetChannelOption(NULL, outConsoleChannel, "-translation", "lf"); 152 | d_SetChannelOption(NULL, outConsoleChannel, "-buffering", "none"); 153 | d_RegisterChannel(d_tcl, outConsoleChannel); 154 | d_SetStdChannel(outConsoleChannel, TCL_STDOUT); 155 | } 156 | Tcl_Channel errConsoleChannel = d_CreateChannel(&consoleErrorChannelType, "stderr", this, TCL_WRITABLE); 157 | if( errConsoleChannel ) 158 | { 159 | d_SetChannelOption(NULL, errConsoleChannel, "-translation", "lf"); 160 | d_SetChannelOption(NULL, errConsoleChannel, "-buffering", "none"); 161 | d_RegisterChannel(d_tcl, errConsoleChannel); 162 | d_SetStdChannel(errConsoleChannel, TCL_STDERR); 163 | } 164 | } 165 | ~Imp() 166 | { 167 | if( d_tcl ) 168 | d_DeleteInterp(d_tcl); 169 | } 170 | 171 | static int get_vlpro_var(ClientData clientData, Tcl_Interp *interp, 172 | int objc, struct Tcl_Obj *const *objv) 173 | { 174 | Imp* imp = static_cast(clientData); 175 | if( objc != 2 ) 176 | { 177 | //qDebug() << "get_vlpro_var wrong number of args" << objc; 178 | imp->d_WrongNumArgs( interp, 1, objv, "string" ); 179 | return TCL_ERROR; 180 | } 181 | const char* name = imp->d_GetString(objv[1]); 182 | //qDebug() << "get_vlpro_var called" << name; 183 | if( imp->d_getVar.d_cb ) 184 | { 185 | const QStringList res = imp->d_getVar.d_cb( name,imp->d_getVar.d_data ); 186 | for( int i = 0; i < res.size(); i++ ) 187 | { 188 | imp->d_AppendElement( interp, res[i].toUtf8().data() ); 189 | } 190 | } 191 | return TCL_OK; 192 | } 193 | 194 | QLibrary d_lib; 195 | Tcl_Interp* d_tcl; 196 | struct GetVarCb { 197 | GetVarCb():d_cb(0),d_data(0){} 198 | TclEngine::GetVar d_cb; 199 | void* d_data; 200 | } d_getVar; 201 | struct WriteLogCb{ 202 | WriteLogCb():d_cb(0),d_data(0){} 203 | TclEngine::WriteLog d_cb; 204 | void* d_data; 205 | } d_writeLog; 206 | }; 207 | 208 | static int writeStdout(ClientData clientData, CONST char * buf, int toWrite, int *errorCode) 209 | { 210 | TclEngine::Imp* imp = static_cast(clientData); 211 | *errorCode = 0; 212 | imp->d_SetErrno(0); 213 | if( imp->d_writeLog.d_cb ) 214 | { 215 | imp->d_writeLog.d_cb( QByteArray::fromRawData(buf,toWrite), false, imp->d_writeLog.d_data ); 216 | return toWrite; 217 | }else 218 | return 0; 219 | } 220 | 221 | static int writeStderr(ClientData clientData, CONST char * buf, int toWrite, int *errorCode) 222 | { 223 | TclEngine::Imp* imp = static_cast(clientData); 224 | *errorCode = 0; 225 | imp->d_SetErrno(0); 226 | if( imp->d_writeLog.d_cb ) 227 | { 228 | imp->d_writeLog.d_cb( QByteArray::fromRawData(buf,toWrite), true, imp->d_writeLog.d_data ); 229 | return toWrite; 230 | }else 231 | return 0; 232 | } 233 | 234 | TclEngine::TclEngine(QObject *parent) : QObject(parent) 235 | { 236 | d_imp = new Imp(); 237 | } 238 | 239 | TclEngine::~TclEngine() 240 | { 241 | delete d_imp; 242 | } 243 | 244 | bool TclEngine::isReady() const 245 | { 246 | return d_imp->d_tcl != 0; 247 | } 248 | 249 | void TclEngine::setGetVar(TclEngine::GetVar gv, void* data) 250 | { 251 | d_imp->d_getVar.d_cb = gv; 252 | d_imp->d_getVar.d_data = data; 253 | } 254 | 255 | void TclEngine::setWriteLog(TclEngine::WriteLog w, void* data) 256 | { 257 | d_imp->d_writeLog.d_cb = w; 258 | d_imp->d_writeLog.d_data = data; 259 | } 260 | 261 | bool TclEngine::runFile(const QString& path) 262 | { 263 | return d_imp->d_EvalFile( d_imp->d_tcl, path.toUtf8().data() ) == TCL_OK; 264 | } 265 | 266 | QString TclEngine::getResult() const 267 | { 268 | return QString::fromUtf8( d_imp->d_GetStringResult(d_imp->d_tcl) ); 269 | } 270 | 271 | TclEngine*TclEngine::addRef() 272 | { 273 | if( s_refCount <= 0 ) 274 | { 275 | //qDebug() << "TCL create"; 276 | s_refCount = 0; 277 | s_inst = new TclEngine(); 278 | } 279 | s_refCount++; 280 | return s_inst; 281 | } 282 | 283 | void TclEngine::release() 284 | { 285 | s_refCount--; 286 | if( s_refCount == 0 ) 287 | { 288 | //qDebug() << "TCL delete"; 289 | delete s_inst; 290 | s_inst = 0; 291 | } 292 | } 293 | 294 | -------------------------------------------------------------------------------- /VlConfigurationFactory.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Rochus Keller 3 | * 4 | * This file is part of the VerilogCreator plugin. 5 | * 6 | * The following is the license that applies to this copy of the 7 | * plugin. For a license to use the plugin under conditions 8 | * other than those described here, please email to me@rochus-keller.ch. 9 | * 10 | * GNU General Public License Usage 11 | * This file may be used under the terms of the GNU General Public 12 | * License (GPL) versions 2.0 or 3.0 as published by the Free Software 13 | * Foundation and appearing in the file LICENSE.GPL included in 14 | * the packaging of this file. Please review the following information 15 | * to ensure GNU General Public Licensing requirements will be met: 16 | * http://www.fsf.org/licensing/licenses/info/GPLv2.html and 17 | * http://www.gnu.org/copyleft/gpl.html. 18 | */ 19 | 20 | #include "VlConfigurationFactory.h" 21 | #include "VlProject.h" 22 | #include "VlIcarusConfiguration.h" 23 | #include "VlVerilatorConfiguration.h" 24 | #include "VlYosysConfiguration.h" 25 | #include "VlTclConfiguration.h" 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | using namespace Vl; 33 | 34 | BuildConfigurationFactory::BuildConfigurationFactory(QObject* parent): 35 | IBuildConfigurationFactory(parent) 36 | { 37 | 38 | } 39 | 40 | int BuildConfigurationFactory::priority(const ProjectExplorer::Target* parent) const 41 | { 42 | return canHandle(parent) ? 0 : -1; 43 | } 44 | 45 | QList BuildConfigurationFactory::availableBuilds(const ProjectExplorer::Target* parent) const 46 | { 47 | QList result; 48 | /* 49 | ProjectExplorer::BuildInfo *info = new ProjectExplorer::BuildInfo(this); 50 | info->typeName = tr("Test Build 1"); 51 | info->kitId = parent->kit()->id(); 52 | result << info; 53 | info = new ProjectExplorer::BuildInfo(this); 54 | info->typeName = tr("Test Build 2"); 55 | info->kitId = parent->kit()->id(); 56 | result << info; 57 | */ 58 | return result; 59 | } 60 | 61 | int BuildConfigurationFactory::priority(const ProjectExplorer::Kit* k, const QString& projectPath) const 62 | { 63 | return 0; 64 | } 65 | 66 | QList BuildConfigurationFactory::availableSetups(const ProjectExplorer::Kit* k, 67 | const QString& projectPath) const 68 | { 69 | // projectPath ist der Pfad zur vlpro-Datei 70 | QList result; 71 | ProjectExplorer::BuildInfo* info = new ProjectExplorer::BuildInfo(this); 72 | info->typeName = IcarusBuildConfig::ID; 73 | info->displayName = IcarusRunConfiguration::Name; 74 | info->buildDirectory = Utils::FileName::fromString(QFileInfo(projectPath).path()); 75 | info->kitId = k->id(); 76 | result << info; 77 | info = new ProjectExplorer::BuildInfo(this); 78 | info->typeName = VerilatorBuildConfig::ID; 79 | info->displayName = VerilatorBuildConfig::Name; 80 | info->buildDirectory = Utils::FileName::fromString(QFileInfo(projectPath).path()); 81 | info->kitId = k->id(); 82 | result << info; 83 | info = new ProjectExplorer::BuildInfo(this); 84 | info->typeName = YosysBuildConfig::ID; 85 | info->displayName = YosysBuildConfig::Name; 86 | info->buildDirectory = Utils::FileName::fromString(QFileInfo(projectPath).path()); 87 | info->kitId = k->id(); 88 | result << info; 89 | info = new ProjectExplorer::BuildInfo(this); 90 | info->typeName = TclBuildConfig::ID; 91 | info->displayName = TclRunConfiguration::Name; 92 | info->buildDirectory = Utils::FileName::fromString(QFileInfo(projectPath).path()); 93 | info->kitId = k->id(); 94 | result << info; 95 | return result; 96 | } 97 | 98 | ProjectExplorer::BuildConfiguration* BuildConfigurationFactory::create(ProjectExplorer::Target* parent, 99 | const ProjectExplorer::BuildInfo* info) const 100 | { 101 | // Wird aufgerufen, wenn Projekt neu erstellt wird bzw. restore noch nicht vorhanden ist 102 | //qDebug() << "BuildConfigurationFactory::create" << info->typeName; 103 | if( info->typeName == IcarusBuildConfig::ID ) 104 | return IcarusBuildConfig::create( parent, info ); 105 | else if( info->typeName == VerilatorBuildConfig::ID ) 106 | return VerilatorBuildConfig::create( parent, info ); 107 | else if( info->typeName == TclBuildConfig::ID ) 108 | return TclBuildConfig::create( parent, info ); 109 | else if( info->typeName == YosysBuildConfig::ID ) 110 | return YosysBuildConfig::create( parent, info ); 111 | else 112 | return 0; 113 | } 114 | 115 | bool BuildConfigurationFactory::canClone(const ProjectExplorer::Target* parent, ProjectExplorer::BuildConfiguration* source) const 116 | { 117 | // Wird nicht direkt aufgerufen, sondern clone wird direkt aufgerufen, wenn in GUI gewählt 118 | Q_UNUSED(parent); 119 | //qDebug() << "BuildConfigurationFactory::canClone" << source->id().toString(); 120 | return false; 121 | // if (!canHandle(parent)) 122 | // return false; 123 | // return source->id() == Constants::BuildConfigId || source->id() == IcarusBuildConfig::ID; 124 | } 125 | 126 | ProjectExplorer::BuildConfiguration* BuildConfigurationFactory::clone(ProjectExplorer::Target* parent, ProjectExplorer::BuildConfiguration* source) 127 | { 128 | //qDebug() << "BuildConfigurationFactory::clone" << source->id().toString(); 129 | if (!canClone(parent, source)) 130 | return 0; 131 | if( IcarusBuildConfig* bc = qobject_cast(source) ) 132 | return new IcarusBuildConfig(parent, bc ); 133 | else if( VerilatorBuildConfig* bc = qobject_cast(source) ) 134 | return new VerilatorBuildConfig(parent, bc ); 135 | else if( TclBuildConfig* bc = qobject_cast(source) ) 136 | return new TclBuildConfig(parent, bc ); 137 | else if( YosysBuildConfig* bc = qobject_cast(source) ) 138 | return new YosysBuildConfig(parent, bc ); 139 | else 140 | return 0; 141 | } 142 | 143 | bool BuildConfigurationFactory::canRestore(const ProjectExplorer::Target* parent, const QVariantMap& map) const 144 | { 145 | Q_UNUSED(parent); 146 | if (!canHandle(parent)) 147 | return false; 148 | const Core::Id id = ProjectExplorer::idFromMap(map); 149 | return id == IcarusBuildConfig::ID || id == VerilatorBuildConfig::ID || 150 | id == YosysBuildConfig::ID || id == TclBuildConfig::ID; 151 | } 152 | 153 | ProjectExplorer::BuildConfiguration* BuildConfigurationFactory::restore(ProjectExplorer::Target* parent, const QVariantMap& map) 154 | { 155 | if (!canRestore(parent, map)) 156 | return 0; 157 | ProjectExplorer::BuildConfiguration* bc = 0; 158 | const Core::Id id = ProjectExplorer::idFromMap(map); 159 | if( id == IcarusBuildConfig::ID ) 160 | bc = new IcarusBuildConfig(parent); 161 | else if( id == VerilatorBuildConfig::ID ) 162 | bc = new VerilatorBuildConfig(parent); 163 | else if( id == TclBuildConfig::ID ) 164 | bc = new TclBuildConfig(parent); 165 | else if( id == YosysBuildConfig::ID ) 166 | bc = new YosysBuildConfig(parent); 167 | if( bc && bc->fromMap(map) ) 168 | return bc; 169 | if( bc ) 170 | delete bc; 171 | return 0; 172 | } 173 | 174 | bool BuildConfigurationFactory::canHandle(const ProjectExplorer::Target* t) const 175 | { 176 | Vl::Project* p = dynamic_cast( t->project() ); 177 | //qDebug() << t->toMap() << p; 178 | return p != 0; 179 | } 180 | 181 | MakeStepFactory::MakeStepFactory(QObject* parent): 182 | IBuildStepFactory(parent) 183 | { 184 | 185 | } 186 | 187 | bool MakeStepFactory::canCreate(ProjectExplorer::BuildStepList* parent, Core::Id id) const 188 | { 189 | Q_UNUSED(parent); 190 | if( id == TclStep::ID ) 191 | return true; 192 | return false; 193 | } 194 | 195 | ProjectExplorer::BuildStep* MakeStepFactory::create(ProjectExplorer::BuildStepList* parent, Core::Id id) 196 | { 197 | Q_UNUSED(parent); 198 | //qDebug() << "MakeStepFactory::create" << id.toString(); 199 | if( id == TclStep::ID ) 200 | return new TclStep(parent); 201 | else 202 | return 0; 203 | } 204 | 205 | bool MakeStepFactory::canClone(ProjectExplorer::BuildStepList* parent, ProjectExplorer::BuildStep* source) const 206 | { 207 | return false; // source->id() == IcarusMakeStep::ID || source->id() == IcarusCleanStep::ID; 208 | } 209 | 210 | ProjectExplorer::BuildStep* MakeStepFactory::clone(ProjectExplorer::BuildStepList* parent, ProjectExplorer::BuildStep* source) 211 | { 212 | return 0; 213 | } 214 | 215 | bool MakeStepFactory::canRestore(ProjectExplorer::BuildStepList* parent, const QVariantMap& map) const 216 | { 217 | Q_UNUSED(parent); 218 | const Core::Id id = ProjectExplorer::idFromMap(map); 219 | return id == IcarusMakeStep::ID || id == IcarusCleanStep::ID || 220 | id == VerilatorMakeStep::ID || id == VerilatorCleanStep::ID || 221 | id == TclStep::ID || 222 | id == YosysMakeStep::ID || id == YosysCleanStep::ID; 223 | } 224 | 225 | ProjectExplorer::BuildStep* MakeStepFactory::restore(ProjectExplorer::BuildStepList* parent, const QVariantMap& map) 226 | { 227 | if (!canRestore(parent, map)) 228 | return 0; 229 | ProjectExplorer::BuildStep* bs = 0; 230 | const Core::Id id = ProjectExplorer::idFromMap(map); 231 | if( id == IcarusMakeStep::ID ) 232 | bs = new IcarusMakeStep(parent); 233 | else if( id == IcarusCleanStep::ID ) 234 | bs = new IcarusCleanStep(parent); 235 | else if( id == VerilatorMakeStep::ID ) 236 | bs = new VerilatorMakeStep(parent); 237 | else if( id == VerilatorCleanStep::ID ) 238 | bs = new VerilatorCleanStep(parent); 239 | else if( id == TclStep::ID ) 240 | bs = new TclStep(parent); 241 | else if( id == YosysMakeStep::ID ) 242 | bs = new YosysMakeStep(parent); 243 | else if( id == YosysCleanStep::ID ) 244 | bs = new YosysCleanStep(parent); 245 | if( bs && bs->fromMap(map) ) 246 | return bs; 247 | if( bs ) 248 | delete bs; 249 | return 0; 250 | } 251 | 252 | QList MakeStepFactory::availableCreationIds(ProjectExplorer::BuildStepList* bc) const 253 | { 254 | Q_UNUSED(bc); 255 | // Die hier angegebenen Steps erscheinen in der Create-Liste der Steps 256 | // canCreate wird dann gar nicht mehr abgefragt, sondern direkt create aufgerufen 257 | QList result; 258 | result << TclStep::ID; 259 | return result; 260 | } 261 | 262 | QString MakeStepFactory::displayNameForId(Core::Id id) const 263 | { 264 | Q_UNUSED(id); 265 | if( id == TclStep::ID ) 266 | return tr("TCL Step"); 267 | return QString(); 268 | } 269 | 270 | 271 | RunConfigurationFactory::RunConfigurationFactory(QObject* parent) 272 | { 273 | 274 | } 275 | 276 | bool RunConfigurationFactory::canCreate(ProjectExplorer::Target* parent, Core::Id id) const 277 | { 278 | return true; 279 | } 280 | 281 | bool RunConfigurationFactory::canRestore(ProjectExplorer::Target* parent, const QVariantMap& map) const 282 | { 283 | return true; 284 | } 285 | 286 | bool RunConfigurationFactory::canClone(ProjectExplorer::Target* parent, ProjectExplorer::RunConfiguration* product) const 287 | { 288 | return false; 289 | } 290 | 291 | ProjectExplorer::RunConfiguration*RunConfigurationFactory::clone(ProjectExplorer::Target* parent, ProjectExplorer::RunConfiguration* product) 292 | { 293 | return 0; 294 | } 295 | 296 | QList RunConfigurationFactory::availableCreationIds(ProjectExplorer::Target* parent, ProjectExplorer::IRunConfigurationFactory::CreationMode mode) const 297 | { 298 | Q_UNUSED(mode); 299 | QList result; 300 | if( parent->project()->id() == Project::ID ) 301 | result << IcarusRunConfiguration::ID; // << TclRunConfiguration::ID; // << VerilatorRunConfiguration::ID; 302 | return result; 303 | } 304 | 305 | QString RunConfigurationFactory::displayNameForId(Core::Id id) const 306 | { 307 | if( id == IcarusRunConfiguration::ID ) 308 | return IcarusRunConfiguration::Name; 309 | else if( id == TclRunConfiguration::ID ) 310 | return TclRunConfiguration::Name; 311 | else 312 | return QString(); 313 | } 314 | 315 | ProjectExplorer::RunConfiguration* RunConfigurationFactory::doCreate(ProjectExplorer::Target* parent, Core::Id id) 316 | { 317 | if( id == IcarusRunConfiguration::ID ) 318 | return new IcarusRunConfiguration(parent); 319 | else if( id == TclRunConfiguration::ID ) 320 | return new TclRunConfiguration(parent); 321 | else 322 | return 0; 323 | } 324 | 325 | ProjectExplorer::RunConfiguration* RunConfigurationFactory::doRestore(ProjectExplorer::Target* parent, const QVariantMap& map) 326 | { 327 | const Core::Id id = ProjectExplorer::idFromMap(map); 328 | if( id == IcarusRunConfiguration::ID ) 329 | return new IcarusRunConfiguration(parent); 330 | else if( id == TclRunConfiguration::ID ) 331 | return new TclRunConfiguration(parent); 332 | else 333 | return 0; 334 | } 335 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![icon](http://software.rochus-keller.ch/VerilogCreator_100.png) 2 | ## Welcome to VerilogCreator 3 | 4 | VerilogCreator is a [QtCreator](https://download.qt.io/official_releases/qtcreator/) plugin. It turns QtCreator into a Verilog 2005 IDE. 5 | 6 | The plugin is still work in progress, but it already has enough functionality to analyze existing code bases or to develop new code. The current version supports Verilog 2005 syntax checking/coloring and semantic code navigation/highlighting; there are build configurations for Icarus, Verilator, Yosys and Tcl. Projects can be configured using a file format similar to qmake. 7 | 8 | ![screenshot](http://software.rochus-keller.ch/VlCreator_screenshot2.png "VerilogCreator Screenshot") 9 | 10 | 11 | ![screenshot](http://software.rochus-keller.ch/VlCreator_screenshot7.png "VerilogCreator Screenshot") 12 | 13 | ### Implemented Features 14 | 15 | - Syntax highlighting (including ifdefed out blocks and markers) 16 | - Context sensitive code completer, see [screenshot](http://software.rochus-keller.ch/vlcreator_completer_screenshot.png) 17 | - Inline code warnings and errors 18 | - Parentheses and begin/end block matching/navigation 19 | - Hover tooltips 20 | - Follow symbol under cursor, follow includes (multi-file support) 21 | - Show where a symbol is used 22 | - Drop-down menu to jump to modules, module instances, functions and tasks in current file 23 | - Outline view; see [screenshot](http://software.rochus-keller.ch/vlcreator_outline_screenshot.png) 24 | - Module locator (global) and symbol locator (current document); see [screenshot 1](http://software.rochus-keller.ch/vlcreator_module_locator_screenshot.png) and [screenshot 2](http://software.rochus-keller.ch/vlcreator_symbol_locator_screenshot.png) 25 | - Syntax based code folding and some other features supported by QtCreator, see http://doc.qt.io/qtcreator/ 26 | - Marker based code folding (MBCF); use section markers like //{ and //}, or //> and //<; see [screenshot 1](http://software.rochus-keller.ch/vlcreator_mbcf_screenshot1.png) and [screenshot 2](http://software.rochus-keller.ch/vlcreator_mbcf_screenshot2.png) 27 | - Project file to configure source files, include dirs, defines and libraries 28 | - Icarus Verilog build and run configuration; directly run compiler and simulator from within QtCreator 29 | - Verilator and Yosys build configurations; generate command files, optional arguments 30 | - Build configuration based on custom Tcl scripts which can access project configuration (e.g. to run Vivado commands) 31 | - Selected optional SystemVerilog syntax extensions such as assert, assume, cover and restrict (see [here for more information](#supported-systemverilog-subset)) 32 | - Supports Standard Delay Format (SDF) files with syntax highlighting, see [screenshot](http://software.rochus-keller.ch/vlcreator_sdf_editor_screenshot.png) 33 | 34 | ### Project file format 35 | 36 | VerilogCreator can either open single verilog files or project configuration files with the suffix ".vlpro". 37 | 38 | The vlpro file can be empty; in that case all Verilog files (default suffix ".v") located in the vlpro directory including subdirectories are assumed to be the source files of the project. 39 | 40 | Vlpro files follow the same syntax as QtCreator pro files (see http://doc.qt.io/qt-5/qmake-project-files.html), but uses other variable names. The following variables are supported: 41 | 42 | `SRCFILES += /path/filename.v` 43 | 44 | `SRCFILES += "/path with whitespace/filename.v"` 45 | 46 | ``` 47 | SRCFILES += /firstpath/filename.v /secondpath/filename.v \ 48 | /thirdpath_on_new_line/filename.v 49 | ``` 50 | 51 | `SRCFILES += /directory_path1/ filename1.v filename2.v /directory_path2/ filename3.v filename4.v` 52 | 53 | The variable `SRCFILES` lets you add source files explicitly to your project. There are different syntax versions. You can add filenames with absolute or relative paths; if you add a directory path only then the following filenames are assumed to belong to the directory with the given path. 54 | Note that path/filenames including whitespace have to be quoted by " ". Also note that you can add more than one element to a line separated by whitespace and that a \ lets you continue on the next line; this applies to all variables. 55 | 56 | `SRCEXT = .v .vl .verilog` 57 | 58 | The `SRCEXT` variable can be used to override the expected suffix of verilog files. Default is ".v". 59 | 60 | 61 | `SRCDIRS += dirpath1 dirpath2 dirpath3*` 62 | 63 | `SRCDIRS += dirpath4 -filename1 -filename2 dirpath5 -filename3` 64 | 65 | With the `SRCDIRS` variable it is possible to add all verilog files in a given directory. All files with a suffix specified in SRCEXT are considered. There are different syntax versions. You can add directories with absolute or relative path. If you postfix the path with an "*" then also all subdirectories are implicitly added. If you want to leave out certain files add the filename to the line prefixed with "-". 66 | 67 | `LIBFILES += ` 68 | 69 | `LIBDIRS += ` 70 | 71 | `LIBEXT = ` 72 | 73 | These variables are used the same way as their SRC counterparts. Use them to add Verilog files which are used but not modified by the present project. 74 | 75 | `INCDIRS += dirpath1 dirpath2` 76 | 77 | The variable `INCDIRS` specifies where the parser looks for include files (included by the Verilog include compiler directive). 78 | 79 | `DEFINES += DISABLE_SV_ASSERTION "E203_PC_SIZE 24"` 80 | 81 | This has the same effect as the Verilog include compiler directive and affects all files. Note that also the syntax corresponds to Verilog defines; since Verilog uses whitespace to separate name and values you have to use quotes in the vlpro file. 82 | There is also a variable `BUILD_UNDEFS` by which defines can be deactivated in the command file generated for Icarus, Verilator and Yosys; you could for example define VERILATOR in the vlpro so VerilogCreator can see it but then use `BUILD_UNDEFS = VERILATOR` to avoid define warnings in Verilator. 83 | 84 | `TOPMOD = picosoc` 85 | 86 | Use TOPMOD to explicitly set the top-level module; this is useful in case there is more than one top-level module in the code base. VerilogCreator does not use this information but hands it over to Icarus, Verilator and Yosys. 87 | 88 | `SVEXT = ` 89 | 90 | This variable is used to tell the parser which files should be considered SystemVerilog files; default is ".sv"; the parser will enable the SV extension for these files in any case, regardless of the UseSvExtension option. 91 | 92 | `CONFIG += UseSvExtension` 93 | 94 | Use this option to enable the SystemVerilog extension for the whole project. Without this option, all files are assumed to be in Verilog 05 format besides the files whose suffix corresponds to one in SVEXT. With the option enabled all files are assumed to be in the supported SystemVerilog 2012 subset. 95 | 96 | `OTHER_FILES += ` 97 | 98 | The variable `OTHER_FILES` lets you add other than source or library files (e.g. SDF files) to your project. The syntax and semantics are the same as with `SRCFILES`. 99 | 100 | ### Supported SystemVerilog subset 101 | 102 | If enabled (see the SVEXT and UseSvExtension project file options) the VerilogCreator plugin supports the following subset of SystemVerilog as specified in IEEE 1800-2012: 103 | 104 | - assert_property_statement, simple_immediate_assert_statement and deferred_immediate_assert_statement 105 | - assume_property_statement, simple_immediate_assume_statement and deferred_immediate_assume_statement 106 | - cover_sequence_statement, cover_property_statement, simple_immediate_cover_statement and deferred_immediate_cover_statement 107 | - restrict_property_statement 108 | - deferred_immediate_assertion_item 109 | - concurrent_assertion_item 110 | - property_spec, without property_instance, checker_instantiation 111 | - sequence_expr, without sequence_abbrev, sequence_match_item, first_match 112 | 113 | ### Download Binaries 114 | 115 | Pre-compiled versions of the VerilogCreator plugin can be downloaded for Windows, Linux and Macintosh as part of the QtcVerilog application. 116 | 117 | See here to learn more: https://github.com/rochus-keller/QtcVerilog/blob/master/README.md 118 | 119 | ### Build Steps 120 | Follow these steps if you want to build VerilogCreator yourself: 121 | 122 | 1. Make sure that QtCreator and the Qt base development package are installed on your system. VerilogCreator was developed and tested with QtCreator 3.4 and Qt 5.4 on Linux. It also compiles with QtCreator 3.6 and Qt 5.7, but not (yet) with QtCreator 4.x (see below). Instead of using QtCreator, you can also use QtcVerilog (see https://github.com/rochus-keller/QtcVerilog). 123 | 1. Create a build directory; let's call it BUILD_DIR 124 | 1. Download the VerilogCreator source code from https://github.com/rochus-keller/VerilogCreator/archive/master.zip and unpack it to the BUILD_DIR; rename the subdirectory to "VerilogCreator". 125 | 1. Download the Verilog parser source code from https://github.com/rochus-keller/Verilog/archive/master.zip and unpack it to the BUILD_DIR; rename "Verilog-Master" to "Verilog". 126 | 1. Download the Sdf parser source code from https://github.com/rochus-keller/Sdf/archive/master.zip and unpack it to the BUILD_DIR; rename "Sdf-Master" to "Sdf". 127 | 1. Download the appropriate version of the QtCreator source code from https://download.qt.io/official_releases/qtcreator/ and unpack it to the BUILD_DIR. Instead of the QtCreator source code you can also use the QtcCreator source code (see https://github.com/rochus-keller/QtcVerilog). 128 | 1. In case you don't have the Tcl development package installed: download http://software.rochus-keller.ch/tcl_headers.zip and unpack it to BUILD_DIR/tcl. 129 | 1. Either set the QTC_SOURCE (path to the QtCreator/QtcVerilog source code directory) and QTC_BUILD (path to the QtCreator/QtcVerilog installation directory) environment variables or directly modify the QTCREATOR_SOURCES and IDE_BUILD_TREE variables in VerilogCreator.pro. 130 | 1. Goto the BUILD_DIR/VerilogCreator subdirectory and execute `QTDIR/bin/qmake VerilogCreator.pro` (see the Qt documentation concerning QTDIR). 131 | 1. Run make; after a couple of minutes the plugin is compiled and automatically deployed to the local QtCreator plugin directory (on Linux to ~/.local/share/data/QtProject/qtcreator/plugins/x.y.z/libVerilogCreator.so) or directly to QtcVerilog. 132 | 1. Start QtCreator/QtcVerilog and check in the "Help/About Plugins..." dialog (section "Other Languages") that the plugin is activated. 133 | 134 | Instead of using qmake and make you can open VerilogCreator.pro using QtCreator and build it there. 135 | 136 | Note that on Windows you also have to compile QtCreator/QtcVerilog itself because you also need the lib files for the plugin dll's (i.e. Core.lib, TextEditor.lib and ProjectExplorer.lib). Compiling QtCreator is not an easy task; compiling QtcVerilog is much easier. 137 | 138 | ### State of Development 139 | Even though I'm using Qt for twenty years and QtCreator for ten years this is my first noteworthy QtCreator plugin. Of course I read all available documentation and watched all available lectures. But still the available information is very sparse, of lesser quality than the Qt documentation and often outdated. So I had to invest half the development time in reverse engineering of the QtCreator 3.4 source code. I don't use QtCreator 4.x yet because I'm working on Ubuntu LTS versions which only have QtCreator 3.x packages and also because I'm fully satisfied with 3.x and the more recent versions run slower and consume more resources. 140 | 141 | I'm aware of the Binary and Source Compatibility rules of QtCreator plugins and managed to make the source code compatible with QtCreator 3.4.x to the latest 3.6.1 using ifdefs. But in QtCreator 4.x they not only have changed some function signatures, but also the architecture to a considerable extent. According to my current state of investigation, managing compatibility with a few ifdefs is no longer feasible; instead it seems necessary to maintain different codebases in parallel to be compatible with both QtCreator 3.x and 4.x and cope with the different architectures at the same time. Thus the question arises whether using QtCreator as the basis for the Verilog IDE is an advantage or rather a disadvantage. If you know a better work-around, please send me an email. 142 | 143 | All in all it is now clear to me why there are comparatively few plugins for QtCreator in all these years and most of them come directly from the Qt Company. Source and binary compatibility between QtCreator versions is not only complex, but a full-blown nightmare. All the more annoying that many changes to the API seem to be purely cosmetic in nature. Unfortunately, you only realize the size and consequences of this problem when you have developed a sufficiently large plugin yourself and built it for several versions of QtCreator, unless you know the source code of QtCreator very well in several versions, which might only be the case for a few people. 144 | 145 | Since I currently consider the effort to reverse engineer each QtCreator version anew and to develop different variants of the code in parallel to be too high, I do it the other way round: instead of adapting the plugin to each major and minor QtCreator version, I offer a simple binary deployment for Linux, Windows and Mac of a lean QtCreator version including VerilogCreator and some other minimal required plugins. See here to learn more: https://github.com/rochus-keller/QtcVerilog. 146 | 147 | ### To do's 148 | 149 | - Documentation 150 | - Semantic indenter (the current one simply adjusts to the previous line) 151 | - Parse output of Icarus/Verilator/Yosys and post it to the Issues pane 152 | - Implement wizzard to add or import files, generate stub modules and automatically update the vlpro file 153 | - Improve hover text 154 | - Implement options dialog (format settings, paths, etc.) 155 | - Improve code completer (for hierarchical identifiers) 156 | - Integrate wave viewer 157 | - Extend SystemVerilog support, goal is to support everything Verilator does. 158 | 159 | ### Support 160 | If you need support or would like to post issues or feature requests please use the Github issue list at https://github.com/rochus-keller/VerilogCreator/issues or send an email to the author. 161 | 162 | 163 | 164 | -------------------------------------------------------------------------------- /VlOutlineMdl.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Rochus Keller 3 | * 4 | * This file is part of the VerilogCreator plugin. 5 | * 6 | * The following is the license that applies to this copy of the 7 | * plugin. For a license to use the plugin under conditions 8 | * other than those described here, please email to me@rochus-keller.ch. 9 | * 10 | * GNU General Public License Usage 11 | * This file may be used under the terms of the GNU General Public 12 | * License (GPL) versions 2.0 or 3.0 as published by the Free Software 13 | * Foundation and appearing in the file LICENSE.GPL included in 14 | * the packaging of this file. Please review the following information 15 | * to ensure GNU General Public Licensing requirements will be met: 16 | * http://www.fsf.org/licensing/licenses/info/GPLv2.html and 17 | * http://www.gnu.org/copyleft/gpl.html. 18 | */ 19 | 20 | #include "VlOutlineMdl.h" 21 | #include "VlModelManager.h" 22 | #include 23 | #include 24 | #include 25 | using namespace Vl; 26 | 27 | OutlineMdl1::OutlineMdl1(QObject *parent) : QAbstractItemModel(parent),d_crm(0) 28 | { 29 | 30 | } 31 | 32 | void OutlineMdl1::setFile(const QString& f) 33 | { 34 | if( d_file == f ) 35 | return; 36 | beginResetModel(); 37 | d_rows.clear(); 38 | if( d_crm ) 39 | disconnect( d_crm, SIGNAL(sigFileUpdated(QString)), this, SLOT( onCrmUpdated(QString) ) ); 40 | d_file = f; 41 | d_crm = ModelManager::instance()->getModelForCurrentProjectOrDirPath(f); 42 | fillTop(); 43 | if( d_crm ) 44 | connect( d_crm, SIGNAL(sigFileUpdated(QString)), this, SLOT( onCrmUpdated(QString) ) ); 45 | endResetModel(); 46 | } 47 | 48 | const CrossRefModel::Symbol*OutlineMdl1::getSymbol(const QModelIndex& index) const 49 | { 50 | if( !index.isValid() || d_crm == 0 ) 51 | return 0; 52 | const int id = index.internalId(); 53 | if( id == 0 ) 54 | return 0; 55 | Q_ASSERT( id <= d_rows.size() ); 56 | return d_rows[id-1].d_sym.data(); 57 | } 58 | 59 | QModelIndex OutlineMdl1::findSymbol(const CrossRefModel::Symbol* s) 60 | { 61 | if( s == 0 || s->tok().d_sourcePath != d_file ) 62 | return QModelIndex(); 63 | 64 | for( int i = 0; i < d_rows.size(); i++ ) 65 | { 66 | if( d_rows[i].d_sym.data() == s ) 67 | return createIndex( i+1, 0, (quint32)i+1 ); 68 | } 69 | return QModelIndex(); 70 | } 71 | 72 | QModelIndex OutlineMdl1::findSymbol(quint32 line, quint16 col) 73 | { 74 | for( int i = 0; i < d_rows.size(); i++ ) 75 | { 76 | if( d_rows[i].d_sym->tok().d_lineNr == line && d_rows[i].d_sym->tok().d_colNr <= col ) 77 | return createIndex( i+1, 0, (quint32)i+1 ); 78 | } 79 | return QModelIndex(); 80 | } 81 | 82 | QModelIndex OutlineMdl1::index(int row, int column, const QModelIndex& parent) const 83 | { 84 | if( parent.isValid() || row < 0 ) 85 | return QModelIndex(); 86 | 87 | return createIndex( row, column, (quint32)row ); 88 | } 89 | 90 | QModelIndex OutlineMdl1::parent(const QModelIndex& index) const 91 | { 92 | return QModelIndex(); 93 | } 94 | 95 | int OutlineMdl1::rowCount(const QModelIndex& parent) const 96 | { 97 | if( parent.isValid() ) 98 | return 0; 99 | else 100 | return d_rows.size() + 1; // +1 wegen 101 | } 102 | 103 | int OutlineMdl1::columnCount(const QModelIndex& parent) const 104 | { 105 | return 1; 106 | } 107 | 108 | 109 | QVariant OutlineMdl1::data(const QModelIndex& index, int role) const 110 | { 111 | if( !index.isValid() || d_crm == 0 ) 112 | return QVariant(); 113 | 114 | const int id = index.internalId(); 115 | if( id == 0 ) 116 | { 117 | switch (role) 118 | { 119 | case Qt::DisplayRole: 120 | if( !d_rows.isEmpty() ) 121 | return tr("