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