@@ -5,12 +5,14 @@ module workspaced.com.ccdb;
5
5
6
6
import std.exception ;
7
7
import std.json ;
8
+ import std.path ;
8
9
import fs = std.file ;
9
10
10
11
import workspaced.api;
11
12
import workspaced.com.dcd;
12
13
13
14
import containers.hashset;
15
+ import workspaced.com.dub;
14
16
15
17
@component(" ccdb" )
16
18
class ClangCompilationDatabaseComponent : ComponentWrapper
@@ -72,6 +74,8 @@ class ClangCompilationDatabaseComponent : ComponentWrapper
72
74
HashSet! string versions;
73
75
HashSet! string debugVersions;
74
76
77
+ _compileCommands.clear();
78
+
75
79
{
76
80
string jsonString = cast (string ) assumeUnique(fs.read(dbPath));
77
81
auto json = parseJSON(jsonString);
@@ -80,12 +84,15 @@ class ClangCompilationDatabaseComponent : ComponentWrapper
80
84
// two represention of the same data
81
85
jsonString = null ;
82
86
83
- json.array
87
+ auto ccRng = json.array
84
88
.map! (jv => CompileCommand.fromJson(jv))
85
- .filter! (cc => cc.isValid)
86
- .each! (cc =>
87
- cc.feedOptions(imports, stringImports, fileImports, versions, debugVersions)
88
- );
89
+ .filter! (cc => cc.isValid);
90
+
91
+ foreach (cc; ccRng)
92
+ {
93
+ cc.feedOptions(imports, stringImports, fileImports, versions, debugVersions);
94
+ _compileCommands[cc.getNormalizedFilePath()] = cc;
95
+ }
89
96
}
90
97
91
98
_importPaths = imports[].array;
@@ -102,6 +109,7 @@ class ClangCompilationDatabaseComponent : ComponentWrapper
102
109
_importFiles = null ;
103
110
_versions = null ;
104
111
_debugVersions = null ;
112
+ _compileCommands.clear();
105
113
}
106
114
107
115
// / Lists all import paths
@@ -134,27 +142,41 @@ class ClangCompilationDatabaseComponent : ComponentWrapper
134
142
return _debugVersions;
135
143
}
136
144
145
+ // / Return the compile command for the given D source file, or null if this file is not
146
+ // / in the database.
147
+ CompileCommand getCompileCommand (string filename) @property
148
+ {
149
+ auto normalized = buildNormalizedPath(filename);
150
+ auto ccp = normalized in _compileCommands;
151
+ if (ccp)
152
+ return ccp.dup ;
153
+ return CompileCommand.init;
154
+ }
155
+
137
156
private :
138
157
139
158
string [] _importPaths, _stringImportPaths, _importFiles, _versions, _debugVersions;
159
+ CompileCommand[string ] _compileCommands;
140
160
}
141
161
142
- private struct CompileCommand
162
+ public struct CompileCommand
143
163
{
144
164
string directory;
145
165
string file;
146
166
string [] args;
147
167
string output;
148
168
149
- static CompileCommand fromJson (JSONValue json)
169
+ private static CompileCommand fromJson (JSONValue json)
150
170
{
151
171
import std.algorithm : map;
152
172
import std.array : array;
153
173
154
174
CompileCommand cc;
155
175
156
- cc.directory = enforce(" directory" in json, " 'directory' missing from Clang compilation database entry" ).str;
157
- cc.file = enforce(" file" in json, " 'file' missing from Clang compilation database entry" ).str;
176
+ cc.directory = enforce(" directory" in json, " 'directory' missing from Clang compilation database entry" )
177
+ .str;
178
+ cc.file = enforce(" file" in json, " 'file' missing from Clang compilation database entry" )
179
+ .str;
158
180
159
181
if (auto args = " arguments" in json)
160
182
{
@@ -189,71 +211,101 @@ private struct CompileCommand
189
211
return true ;
190
212
}
191
213
192
- void feedOptions (
193
- ref HashSet! string imports,
194
- ref HashSet! string stringImports,
195
- ref HashSet! string fileImports,
196
- ref HashSet! string versions,
197
- ref HashSet! string debugVersions)
198
- {
199
- import std.algorithm : startsWith;
200
-
201
- enum importMark = " -I" ; // optional =
202
- enum stringImportMark = " -J" ; // optional =
203
- enum fileImportMark = " -i=" ;
204
- enum dmdVersionMark = " -version=" ;
205
- enum ldcVersionMark = " --d-version=" ;
206
- enum dmdDebugMark = " -debug=" ;
207
- enum ldcDebugMark = " --d-debug=" ;
214
+ bool opCast (T:bool )() const {
215
+ return isValid;
216
+ }
208
217
209
- foreach (arg; args)
210
- {
211
- const mark = arg.startsWith(
212
- importMark, stringImportMark, fileImportMark, dmdVersionMark, ldcVersionMark, dmdDebugMark, ldcDebugMark,
213
- );
218
+ @property CompileCommand dup () const {
219
+ return CompileCommand (directory, file, args.dup , output);
220
+ }
214
221
215
- switch (mark)
216
- {
217
- case 0 :
218
- break ;
219
- case 1 :
220
- case 2 :
221
- if (arg.length == 2 )
222
- break ; // ill-formed flag, we don't need to care here
223
- const st = arg[2 ] == ' =' ? 3 : 2 ;
224
- const path = getPath(arg[st .. $]);
225
- if (mark == 1 )
226
- imports.put(path);
227
- else
228
- stringImports.put(path);
229
- break ;
230
- case 3 :
231
- fileImports.put(getPath(arg[fileImportMark.length .. $]));
232
- break ;
233
- case 4 :
234
- version s.put(arg[dmdVersionMark.length .. $]);
235
- break ;
236
- case 5 :
237
- version s.put(arg[ldcVersionMark.length .. $]);
238
- break ;
239
- case 6 :
240
- debugVersions.put(arg[dmdDebugMark.length .. $]);
241
- break ;
242
- case 7 :
243
- debugVersions.put(arg[ldcDebugMark.length .. $]);
244
- break ;
245
- default :
246
- break ;
247
- }
248
- }
222
+ string getNormalizedFilePath () const
223
+ {
224
+ return getPath (file).buildNormalizedPath();
249
225
}
250
226
251
- string getPath (string filename)
227
+ string getPath (string filename) const
252
228
{
253
229
import std.path : absolutePath;
254
230
255
231
return absolutePath (filename, directory);
256
232
}
233
+
234
+ Future! (BuildIssue[]) run () const {
235
+ import std.algorithm : canFind, remove;
236
+ import std.process : Config, execute;
237
+
238
+ return Future! (BuildIssue[]).async({
239
+ trace(" stripping color from " , args);
240
+ string [] program = args.dup .remove! (a => a.canFind(" -color=on" ) || a.canFind(" -enable-color" ));
241
+ trace(" running " , program);
242
+ auto res = execute(program, null , Config.none, size_t .max, directory);
243
+ trace(res.status, " " , res.output);
244
+ auto issues = parseBuildIssues(res.output);
245
+ trace(" found " , issues.length, " issue(s)!" );
246
+ return issues;
247
+ });
248
+ }
249
+ }
250
+
251
+ void feedOptions (
252
+ in CompileCommand cc,
253
+ ref HashSet! string imports,
254
+ ref HashSet! string stringImports,
255
+ ref HashSet! string fileImports,
256
+ ref HashSet! string versions,
257
+ ref HashSet! string debugVersions)
258
+ {
259
+ import std.algorithm : startsWith;
260
+
261
+ enum importMark = " -I" ; // optional =
262
+ enum stringImportMark = " -J" ; // optional =
263
+ enum fileImportMark = " -i=" ;
264
+ enum dmdVersionMark = " -version=" ;
265
+ enum ldcVersionMark = " --d-version=" ;
266
+ enum dmdDebugMark = " -debug=" ;
267
+ enum ldcDebugMark = " --d-debug=" ;
268
+
269
+ foreach (arg; cc.args)
270
+ {
271
+ const mark = arg.startsWith(
272
+ importMark, stringImportMark, fileImportMark, dmdVersionMark, ldcVersionMark, dmdDebugMark, ldcDebugMark,
273
+ );
274
+
275
+ switch (mark)
276
+ {
277
+ case 0 :
278
+ break ;
279
+ case 1 :
280
+ case 2 :
281
+ if (arg.length == 2 )
282
+ break ; // ill-formed flag, we don't need to care here
283
+ const st = arg[2 ] == ' =' ? 3 : 2 ;
284
+ const path = cc.getPath(arg[st .. $]);
285
+ if (mark == 1 )
286
+ imports.put(path);
287
+ else
288
+ stringImports.put(path);
289
+ break ;
290
+ case 3 :
291
+ fileImports.put(cc.getPath(arg[fileImportMark.length .. $]));
292
+ break ;
293
+ case 4 :
294
+ version s.put(arg[dmdVersionMark.length .. $]);
295
+ break ;
296
+ case 5 :
297
+ version s.put(arg[ldcVersionMark.length .. $]);
298
+ break ;
299
+ case 6 :
300
+ debugVersions.put(arg[dmdDebugMark.length .. $]);
301
+ break ;
302
+ case 7 :
303
+ debugVersions.put(arg[ldcDebugMark.length .. $]);
304
+ break ;
305
+ default :
306
+ break ;
307
+ }
308
+ }
257
309
}
258
310
259
311
private string [] unescapeCommand (string cmd)
0 commit comments