1 #ifndef Header_SyntaxCheck
2 #define Header_SyntaxCheck
3 
4 #include "mostQtHeaders.h"
5 #include "smallUsefulFunctions.h"
6 #include "latexparser/latexparser.h"
7 #include "qdocumentline_p.h"
8 #include <QThread>
9 #include <QSemaphore>
10 #include <QMutex>
11 #include <QQueue>
12 
13 class SpellerUtility;
14 /*!
15  * \brief store information on open environments
16  */
17 class Environment
18 {
19 public:
Environment()20     Environment(): id(-1), excessCol(0), dlh(nullptr),endingColumn(-1) , ticket(0), level(0) {} ///< constructor
21 
22 	QString name; ///< name of environment, partially an alias is used, e.g. math instead of '$'
23     QString origName; ///< original name of environment if alias is used, otherwise empty
24 	int id; ///< mostly unused, contains the number of columns for tabular-environments
25 	int excessCol; ///< number of unused tabular-columns if columns are strechted over several text lines
26 	QDocumentLineHandle *dlh; ///< linehandle of starting line
27     int startingColumn;
28     int endingColumn;
29 	int ticket;
30     int level; ///< command level (see tokens) in order to handle nested commands like \shortstack
31 
32 	bool operator ==(const Environment &env) const
33 	{
34         return (name == env.name) && (id == env.id) && (excessCol == env.excessCol) && (origName == env.origName) && (level == env.level);
35 	}
36 	bool operator !=(const Environment &env) const
37 	{
38         return (name != env.name) || (id != env.id) || (excessCol != env.excessCol) || (origName != env.origName) || (level != env.level);
39 	}
40 };
41 
42 typedef QStack<Environment> StackEnvironment;
43 
Q_DECLARE_METATYPE(StackEnvironment)44 Q_DECLARE_METATYPE(StackEnvironment)
45 
46 class SyntaxCheck : public SafeThread
47 {
48 	Q_OBJECT
49 
50 public:
51     /*!
52      * \brief type of error
53      */
54 	enum ErrorType {
55 		ERR_none, ///< no error
56 		ERR_unrecognizedEnvironment, ///< environment unknown
57 		ERR_unrecognizedCommand, ///< command unknown
58 		ERR_unrecognizedMathCommand, ///< unknown command for math environment
59 		ERR_unrecognizedTabularCommand, ///< unknown command for tabular environment
60 		ERR_TabularCommandOutsideTab, ///< tabular command outside tabular (e.g. \hline)
61 		ERR_MathCommandOutsideMath, ///< math command outside of math env
62 		ERR_TabbingCommandOutside, ///< tabbing command outside of tabbing env
63 		ERR_tooManyCols, ///< tabular has more columns in line than in definition
64 		ERR_tooLittleCols, ///< tabular has fewer columns in line than in definition
65 		ERR_missingEndOfLine, ///< unused
66 		ERR_closingUnopendEnv, ///< end{env} without corrresponding begin{env}
67 		ERR_EnvNotClosed, ///< end{env} missing
68 		ERR_unrecognizedKey, ///< in key/value argument, an unknown key is used
69 		ERR_unrecognizedKeyValues, ///< in key/value argument, an unknown value is used for a key
70 		ERR_commandOutsideEnv, ///< command used outside of designated environment (similar math command outside math)
71         ERR_spelling, ///< syntax error of text word (spell checker)
72         ERR_highlight, ///< arbitraty format for highlighting (math,verbatim,picture)
73 		ERR_MAX  // always last
74 	};
75     /*!
76      * \brief info which is queued for syntaxchecking
77      */
78 	struct SyntaxLine {
79 		StackEnvironment prevEnv; ///< environmentstack at start of line
80 		TokenStack stack; ///< tokenstack at start of line (open arguments)
81 		int ticket; ///< ticket number
82 		bool clearOverlay; ///< clear syntax overlay, sometimes not necessary as it was done somewhere else
83 		QDocumentLineHandle *dlh; ///< linehandle
84         int hint; ///< hint on lineNumber for faster look-up
85         bool initialRun;
86 	};
87 
88     /*!
89      * \brief structure to describe an syntax error
90      */
91 	struct Error {
92 		QPair<int, int> range; ///<  start,stop of error marker
93 		ErrorType type; ///< type of error
94         int format; ///< arbitrary format to used instead of error marker
95 	};
96 
97 	typedef QList<Error > Ranges;
98 
99     explicit SyntaxCheck(QObject *parent = nullptr);
100 
101     void putLine(QDocumentLineHandle *dlh, StackEnvironment previous, TokenStack stack, bool clearOverlay = false,int hint=-1);
102 	void stop();
103 	void setErrFormat(int errFormat);
104     QString getErrorAt(QDocumentLineHandle *dlh, int pos, StackEnvironment previous, TokenStack stack);
105 #ifndef NO_TESTS
106 	void waitForQueueProcess(void);
107 #endif
108 	static int containsEnv(const LatexParser &parser, const QString &name, const StackEnvironment &envs, const int id = -1);
109 	int topEnv(const QString &name, const StackEnvironment &envs, const int id = -1);
110 	bool checkCommand(const QString &cmd, const StackEnvironment &envs);
111 	static bool equalEnvStack(StackEnvironment env1, StackEnvironment env2);
112 
113 	void setLtxCommands(const LatexParser &cmds);
114     void setSpeller(SpellerUtility *su);
115     void setReplacementList(QMap<QString, QString> replacementList);
116     void setFormats(QMap<QString, int> formatList);
117     void enableSyntaxCheck(const bool enable);
118 
119 	void markUnclosedEnv(Environment env);
120 
121 signals:
122     void checkNextLine(QDocumentLineHandle *dlh, bool clearOverlay, int ticket, int hint); ///< enqueue next line for syntax checking as context has changed
123 
124 protected:
125 	void run();
126     void checkLine(const QString &line, Ranges &newRanges, StackEnvironment &activeEnv, QDocumentLineHandle *dlh, TokenList &tl, TokenStack stack, int ticket, int commentStart=-1);
127 
128 private:
129 	QQueue<SyntaxLine> mLines;
130 	QSemaphore mLinesAvailable;
131 	QMutex mLinesLock;
132 	QAtomicInt mLinesEnqueuedCounter; //!< Total number of lines enqueued from beginning. Never decremented.
133 	bool stopped;
134     bool mSyntaxChecking; //! show/hide syntax errors
135     int syntaxErrorFormat;
136 	LatexParser *ltxCommands;
137 
138 	LatexParser newLtxCommands;
139 	bool newLtxCommandsAvailable;
140 	QMutex mLtxCommandLock;
141 	bool stackContainsDefinition(const TokenStack &stack) const;
142 
143     SpellerUtility *speller,*newSpeller;
144 
145     QMap<QString,QString> newReplacementList,mReplacementList;
146     QMap<QString,int> newFormatList,mFormatList;
147 
148 };
149 
150 #endif // SYNTAXCHECK_H
151