-
Notifications
You must be signed in to change notification settings - Fork 2
/
AoCodeModel.h
254 lines (217 loc) · 7.64 KB
/
AoCodeModel.h
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
#ifndef LISACODEMODEL_H
#define LISACODEMODEL_H
/*
* Copyright 2023 Rochus Keller <mailto:me@rochus-keller.ch>
*
* This file is part of the ActiveOberon parser/navigator project.
*
* The following is the license that applies to this copy of the
* file. For a license to use the file under conditions
* other than those described here, please email to me@rochus-keller.ch.
*
* GNU General Public License Usage
* This file may be used under the terms of the GNU General Public
* License (GPL) versions 2.0 or 3.0 as published by the Free Software
* Foundation and appearing in the file LICENSE.GPL included in
* the packaging of this file. Please review the following information
* to ensure GNU General Public Licensing requirements will be met:
* http://www.fsf.org/licensing/licenses/info/GPLv2.html and
* http://www.gnu.org/copyleft/gpl.html.
*/
// Adopted from the Lisa Pascal Navigator
#include <QAbstractItemModel>
#include <QHash>
#include <AoFileSystem.h>
#include <QSharedData>
#include "AoRowCol.h"
namespace Ao
{
class Scope;
class UnitFile;
class Symbol;
class Thing
{
public:
enum Kind { Undefined,
/* Declaration: */ Const, TypeDecl, Var, Proc, Attribute, Param, Field,
Module, Self, Import,
/* Scope: */ Body, Members,
/* UnitFile: */ Unit,
/* CodeFolder: */ Folder
};
quint8 d_kind;
enum Visi { NA, ReadOnly, Public };
quint8 d_visi;
bool d_active;
quint8 d_exclusive; // count exclusive attrs in proc body
virtual FilePos getLoc() const { return FilePos(); }
virtual quint16 getLen() const { return 0; }
virtual QString getName() const;
virtual const FileSystem::File* getFile() const { return 0; }
bool isDeclaration() const { return d_kind >= Const && d_kind <= Import; }
const char* typeName() const;
Thing():d_kind(Undefined),d_visi(0),d_active(false),d_exclusive(0){}
virtual ~Thing();
};
class Type : public QSharedData
{
public:
typedef QExplicitlySharedDataPointer<Type> Ref;
enum Kind { Undefined, Pointer, Array, Record, Class, Procedural
};
Type::Ref d_type;
Scope* d_members; // owns
quint8 d_kind;
Type():d_type(0), d_members(0),d_kind(Undefined) {}
~Type();
};
class Declaration : public Thing
{
public:
Scope* d_body; // owns, unless Import; used for Proc, Module and Import
Type::Ref d_type;
QByteArray d_name;
FilePos d_loc; // place in unit or any include file where the decl is actually located
Scope* d_owner;
typedef QList<Symbol*> SymList;
typedef QHash<QString,SymList> Refs;
Refs d_refs; // file path -> Symbols in it, not owned
Symbol* d_me; // this is the symbol by which the decl itself is represented in the file
FilePos getLoc() const { return d_loc; }
quint16 getLen() const { return d_name.size(); }
QString getName() const;
UnitFile* getUnitFile() const; // only for ownership, not for actual file position
Declaration():d_body(0),d_owner(0),d_me(0),d_type(0){}
~Declaration();
};
class Scope : public Thing
{
public:
QList<Declaration*> d_order; // owns
Thing* d_owner; // either declaration or unit file or class or 0
Scope* d_outer; // surrounding scope for blocks, inherited scope for record/object
Scope* d_altOuter; // local scope of the record/object declaration
Type* d_type; // for object member scopes pointing to the object
UnitFile* getUnitFile() const;
Declaration* findDecl(const char* id, bool useAlt = false) const;
void clear();
Scope():d_owner(0),d_outer(0),d_altOuter(0),d_type(0){}
~Scope();
};
class Symbol
{
public:
Declaration* d_decl;
RowCol d_loc; // the position of the symbol in the file (declaration has other position, but same length)
Symbol():d_decl(0){}
};
class UnitFile;
class CodeFolder;
class CodeFile : public Thing
{
public:
const FileSystem::File* d_file;
CodeFolder* d_folder;
UnitFile* toUnit();
QString getName() const;
const FileSystem::File* getFile() const { return d_file; }
CodeFile():d_file(0),d_folder(0) {}
~CodeFile();
};
class UnitFile : public CodeFile
{
public:
Scope* d_body; // owns (technical scope with only one module declaration member)
Declaration* d_module; // points to the corresponding declaration in d_body
QList<UnitFile*> d_import;
typedef QList<Symbol*> SymList;
QHash<QString,SymList> d_syms; // owns, all things we can click on in a code file ordered by row/col
QByteArrayList findUses() const;
UnitFile():d_body(0),d_module(0) { d_kind = Unit; }
~UnitFile();
};
class CodeFolder : public Thing
{
public:
FileSystem::Dir* d_dir;
QList<CodeFolder*> d_subs; // owns
QList<CodeFile*> d_files; // owns
QString getName() const;
void clear();
CodeFolder():d_dir(0){ d_kind = Folder; }
~CodeFolder() { clear(); }
};
struct ModelItem
{
Thing* d_thing;
QList<ModelItem*> d_children;
ModelItem* d_parent;
ModelItem(ModelItem* p = 0, Thing* t = 0):d_parent(p),d_thing(t){ if( p ) p->d_children.append(this); }
~ModelItem() { foreach( ModelItem* s, d_children ) delete s; }
static bool lessThan( const ModelItem* lhs, const ModelItem* rhs);
};
class ItemModel : public QAbstractItemModel
{
Q_OBJECT
public:
explicit ItemModel(QObject *parent = 0);
const Thing* getThing(const QModelIndex& index) const;
QModelIndex findThing(const Thing* nt) const;
// overrides
int columnCount ( const QModelIndex & parent = QModelIndex() ) const { return 1; }
QVariant data ( const QModelIndex & index, int role = Qt::DisplayRole ) const;
QModelIndex index ( int row, int column, const QModelIndex & parent = QModelIndex() ) const;
QModelIndex parent ( const QModelIndex & index ) const;
int rowCount ( const QModelIndex & parent = QModelIndex() ) const;
Qt::ItemFlags flags ( const QModelIndex & index ) const { return Qt::ItemIsEnabled | Qt::ItemIsSelectable; }
protected:
QModelIndex findThing(const ModelItem* slot,const Thing* nt) const;
ModelItem d_root;
};
class CodeModel : public ItemModel
{
Q_OBJECT
public:
explicit CodeModel(QObject *parent = 0);
bool load( const QString& rootDir );
Symbol* findSymbolBySourcePos(const QString& path, int line, int col) const;
FileSystem* getFs() const { return d_fs; }
quint32 getSloc() const { return d_sloc; }
CodeFile* getCodeFile(const QString& path) const;
UnitFile* getUnitFile(const QString& path) const;
Ranges getMutes( const QString& path );
int getErrCount() const { return d_errCount; }
Declaration* getSystem() { return &d_system; }
Scope* getAttrs() { return &d_attrs; }
Scope* getPredecls() { return &d_predecls; }
// overrides
QVariant data ( const QModelIndex & index, int role = Qt::DisplayRole ) const;
protected:
void parseAndResolve(UnitFile*);
private:
void fillFolders(ModelItem* root, const FileSystem::Dir* super, CodeFolder* top, QList<ModelItem*>& fileSlots);
FileSystem* d_fs;
CodeFolder d_top;
Declaration d_system;
Scope d_attrs, d_predecls;
QHash<const FileSystem::File*,UnitFile*> d_map1;
QHash<QString,CodeFile*> d_map2; // real path -> file
quint32 d_sloc; // number of lines of code without empty or comment lines
QHash<QString,Ranges> d_mutes;
int d_errCount;
};
class ModuleDetailMdl : public ItemModel
{
Q_OBJECT
public:
explicit ModuleDetailMdl(QObject *parent = 0);
void load(Scope* impl);
// overrides
QVariant data ( const QModelIndex & index, int role = Qt::DisplayRole ) const;
private:
void fillItems(ModelItem* parentItem, Scope* scope);
void fillSubs(ModelItem* parentItem, Scope* scope);
Scope* d_impl;
};
}
#endif // LISACODEMODEL_H