summaryrefslogtreecommitdiffstats
path: root/buildtools/qmake/scope.h
blob: e8f40eb956f692438f8d31723b3775cc11b8d0a9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
/***************************************************************************
*   Copyright (C) 2006 by Andreas Pakulat                                 *
*   apaku@gmx.de                                                          *
*                                                                         *
*   This program is free software; you can redistribute it and/or modify  *
*   it under the terms of the GNU General Public License as published by  *
*   the Free Software Foundation; either version 2 of the License, or     *
*   (at your option) any later version.                                   *
*                                                                         *
***************************************************************************/

#ifndef _SCOPE_H_
#define _SCOPE_H_

#include <qstring.h>
#include <qstringlist.h>
#include <qmap.h>
#include <set>

#include "qmakeast.h"
#include "qmakedefaultopts.h"

#ifdef DEBUG
#include "qmakeastvisitor.h"
#endif

class Scope;
class TrollProjectPart;

class Scope
{
public:

    enum ScopeType {
        ProjectScope,
        FunctionScope,
        SimpleScope,
        IncludeScope,
        InvalidScope
    };
    static const QStringList KnownVariables;
    static const QStringList KnownConfigValues;

    Scope( const QMap<QString, QString>& env, const QString &filename, TrollProjectPart* part );
    ~Scope();

    void saveToFile() const;

    // Changing variable values
    void addToPlusOp( const QString& variable, const QStringList& values );
    void removeFromPlusOp( const QString& variable, const QStringList& values );
    void addToMinusOp( const QString& variable, const QStringList& values );
    void removeFromMinusOp( const QString& variable, const QStringList& values );
    void addToEqualOp( const QString& variable, const QStringList& values );
    void removeFromEqualOp( const QString& variable, const QStringList& values );
    void setPlusOp( const QString& variable, const QStringList& values );
    void setEqualOp( const QString& variable, const QStringList& values );
    void setMinusOp( const QString& variable, const QStringList& values );

    // Checks wether a line like VAR = exists in this subscope
    bool isVariableReset( const QString& var );

    // Fetch the valuelist for the variable op combination inside this scope
    QStringList variableValuesForOp( const QString& variable, const QString& op ) const;

    // Fetch the variable values by running over the statements and adding/removing/setting
    // as the encountered op's say, begin with the parent projects variableValues list
    QStringList variableValues( const QString& variable, bool checkIncParent = true, bool fetchFromParent = true, bool evaluateSubScopes = false );

    // Remove a variable+Op combination from the scope, if existant
    void removeVariable( const QString& var, const QString& op );

    // Getting to know what type of scope this is
    ScopeType scopeType() const;

    // This returns the function+args, the scopename or the pro/pri file
    // depending on the type of scope
    QString scopeName() const;

    // Returns the projectName for this scope, this is equal to the last part of the projectDir()
    QString projectName() const;

    // Returns just the filename of this project's .pro file
    QString fileName() const;

    // Returns the absolute path of the dir containing the .pro file
    QString projectDir() const;

    // get the parent Scope
    Scope* parent() const { return m_parent; }

    // Fetching sub-scopes
    const QValueList<Scope*> scopesInOrder() const { return m_scopes.values(); }
    // Working on SubScopes
    /*
     * creates a new function scope at the end of this (Sub-)AST and returns the Scope wrapping it
     */
    Scope* createFunctionScope( const QString& funcName, const QString& args );
    /*
     * creates a new simple scope at the end of this (Sub-)AST and returns the Scope wrapping it
     */
    Scope* createSimpleScope( const QString& scopename );

    /*
     * creates a new function scope at the end of this (Sub-)AST
     * and a new include scope inside the new function scope.
     * It returns the Scope wrapping the include-AST, the function scope AST
     * can be accessed easily using the parent() method.
     */
    Scope* createIncludeScope( const QString& includeFile, bool negate = false );

    /*
     * creates a new subproject in dir (create's dir if necessary)
     * If this scope is not a project scope the subproject will be added to this
     * Scope only, i.e. it is not seen in the project-files list of subdirs
     */
    Scope* createSubProject( const QString& dir );

    /* delete the given function scope */
    bool deleteFunctionScope( unsigned int );
    /* delete the given simple scope */
    bool deleteSimpleScope( unsigned int );
    /* delete the given include scope */
    bool deleteIncludeScope( unsigned int );
    /* deletes the subproject (including the subdir if deleteSubdir is true) */
    bool deleteSubProject( unsigned int, bool deleteSubdir );

    /* find out wether the project is Qt4 or Qt3 */
    bool isQt4Project() const ;

    /* Provide a Map of Custom variables */
    const QMap<unsigned int, QMap<QString, QString> > customVariables() const;

    unsigned int addCustomVariable( const QString& var, const QString& op, const QString& values );

    /* Removes the variable with the given id if it exists */
    void removeCustomVariable( unsigned int );

    /* Update the values of the variable/operation combo var+op to values */
    void updateCustomVariable( unsigned int, const QString&, const QString& , const QString& );

    // Checks wether a QStringList contains any values that are not whitespace or \\n
    static bool listIsEmpty( const QStringList& values );

    /* returns wether this is an enabled subproject or a disabled one */
    bool isEnabled() { return m_isEnabled; }

    QStringList cleanStringList(const QStringList& list) const;

    /* Reload a project scope */
    void reloadProject();

    /* creates a new disabled Scope child and add SUBDIRS -= dir to this scope */
    Scope* disableSubproject( const QString& );

    /* return the "position" of this scope in the list of scopes */
    unsigned int getNum() { return m_num; }

    QStringList allFiles( const QString& );

    QString resolveVariables( const QString& ) const;

    QString findCustomVarForPath( const QString& );

#ifdef DEBUG
    void printTree();
#endif

private:

    // Builds the scope-lists and the customVariables list
    void init();

    /*
     * Updates the given Variable+op with the values, if removeFromOp is true it removes the values, else it adds them
     * this works it's way back through the current scope and changes the last occurence of op to
     * include all new values.
     *
     * Depending on "op" it might end the search earlier (if op is += it also stops at =)
     *
     * This also removes the values from other assignments if the operation is not op, i.e.
     * if op is += removes values from any occurence of -=
     * if op is -= removes values from any occurence of = and +=
     * if op is = removes values frmo any occurence of -=
     */
    void updateVariable( const QString& variable, const QString& op, const QStringList& values, bool removeFromOp );

    /*
     * Helper Function to change the origValues list with the values from newValues
     * depending on the state of "remove" either adds or removes all entries from newValues
     * to origValues if they didn't exist there yet
     */
    void updateValues( QStringList& origValues, const QStringList& newValues, bool remove = false, QString indent = "  " );

    /*
     * Finds an existing variable, returns the end() of the statemenst if it is not found
     */
    QValueList<QMake::AST*>::iterator findExistingVariable( const QString& variable );

    // Private constructors for easier subscope creation
    /*
     * just initializes the lists from the scope
     */
    Scope( const QMap<QString, QString>& env, unsigned int num, Scope* parent, QMake::ProjectAST* root, QMakeDefaultOpts*, TrollProjectPart* part );
    /*
     * reads the given filename and parses it. If it doesn't exist creates an empty
     * ProjectAST with the given filename
     */
    Scope( const QMap<QString, QString>& env, unsigned int num, Scope* parent, const QString& filename, TrollProjectPart* part, bool isEnabled = true );
    /*
     * Creates a scope for an include statement, parses the file and initializes the Scope
     * Create an empty ProjectAST if the file cannot be found or parsed.
     */
    Scope( const QMap<QString, QString>& env, unsigned int num, Scope* parent, QMake::IncludeAST* incast, const QString& path, const QString& incfile, QMakeDefaultOpts*, TrollProjectPart* part );


    // runs through the statements until stopHere is found (or the end is reached, if stopHere is 0),
    // using the given list as startvalue
    // Changes the list using the +=, -=, = operations accordingly
    void calcValuesFromStatements( const QString& variable, QStringList& result, bool, QMake::AST* stopHere = 0, bool fetchFromParent = true, bool setDefault = true, bool evaluateSubScopes = false ) const;

    // Check wether the two operators are compatible
    static bool isCompatible( const QString& op1, const QString& op2);

    // Check wether the 2 lists are equal, regardless of element order.
    static bool listsEqual(const QStringList& , const QStringList& );

    // Load and Save project files, these only work on ProjectScope's
    bool loadFromFile( const QString& filename );

    QString funcScopeKey( QMake::ProjectAST* funcast ) const { return funcast->scopedID + "(" + funcast->args + ")"; }

    unsigned int getNextScopeNum() { if( m_scopes.isEmpty() ) return 0; else return (m_scopes.keys().last()+1); }

    QStringList lookupVariable( const QString& var );

    QStringList resolveVariables( const QStringList&, QMake::AST* = 0 ) const;
    QStringList variableValues( const QString& variable, QMake::AST*, bool fetchFromParent = true ) const;
    QString resolveVariables( const QString& , QMake::AST* ) const;

    // This function determines the currently used String for fileending, it can be \n, \r or \r\n
    QString getLineEndingString() const;
    bool isComment( const QString& ) const;
    bool containsContinue( const QString& ) const;
    void allFiles( const QString&, std::set<QString>& );

    void loadDefaultOpts();

    QMake::ProjectAST* m_root;
    QMake::IncludeAST* m_incast;
    QMap<unsigned int, QMake::AssignmentAST*> m_customVariables;
    QMap<unsigned int, Scope*> m_scopes;
    Scope* m_parent;
    unsigned int m_maxCustomVarNum;

    QString replaceWs(QString);


    // The "position" inside the parent scope that this scope starts at
    unsigned int m_num;
    bool m_isEnabled;
    TrollProjectPart* m_part;
    QMakeDefaultOpts* m_defaultopts;
    QMap<QString, QStringList> m_varCache;
    QMap<QString,QString> m_environment;

#ifdef DEBUG
    class PrintAST : QMake::ASTVisitor
    {

    public:
        PrintAST();
        virtual void processProject( QMake::ProjectAST* p );
        virtual void enterRealProject( QMake::ProjectAST* p );

        virtual void leaveRealProject( QMake::ProjectAST* p );

        virtual void enterScope( QMake::ProjectAST* p );

        virtual void leaveScope( QMake::ProjectAST* p );

        virtual void enterFunctionScope( QMake::ProjectAST* p );

        virtual void leaveFunctionScope( QMake::ProjectAST* p );

        virtual void processAssignment( QMake::AssignmentAST* a);

        virtual void processNewLine( QMake::NewLineAST* n);

        virtual void processComment( QMake::CommentAST* a);

        virtual void processInclude( QMake::IncludeAST* a);

        QString replaceWs(QString);

    private:
        QString getIndent();
        int indent;

    };
#endif

};

#endif

// kate: space-indent on; indent-width 4; tab-width 4; replace-tabs on