Skip to content

Commit 7d1f57f

Browse files
committed
CCDB component enhanced with CompileCommand
1 parent 3286258 commit 7d1f57f

File tree

1 file changed

+117
-65
lines changed
  • workspace-d/source/workspaced/com

1 file changed

+117
-65
lines changed

workspace-d/source/workspaced/com/ccdb.d

+117-65
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,14 @@ module workspaced.com.ccdb;
55

66
import std.exception;
77
import std.json;
8+
import std.path;
89
import fs = std.file;
910

1011
import workspaced.api;
1112
import workspaced.com.dcd;
1213

1314
import containers.hashset;
15+
import workspaced.com.dub;
1416

1517
@component("ccdb")
1618
class ClangCompilationDatabaseComponent : ComponentWrapper
@@ -72,6 +74,8 @@ class ClangCompilationDatabaseComponent : ComponentWrapper
7274
HashSet!string versions;
7375
HashSet!string debugVersions;
7476

77+
_compileCommands.clear();
78+
7579
{
7680
string jsonString = cast(string) assumeUnique(fs.read(dbPath));
7781
auto json = parseJSON(jsonString);
@@ -80,12 +84,15 @@ class ClangCompilationDatabaseComponent : ComponentWrapper
8084
// two represention of the same data
8185
jsonString = null;
8286

83-
json.array
87+
auto ccRng = json.array
8488
.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+
}
8996
}
9097

9198
_importPaths = imports[].array;
@@ -102,6 +109,7 @@ class ClangCompilationDatabaseComponent : ComponentWrapper
102109
_importFiles = null;
103110
_versions = null;
104111
_debugVersions = null;
112+
_compileCommands.clear();
105113
}
106114

107115
/// Lists all import paths
@@ -134,27 +142,41 @@ class ClangCompilationDatabaseComponent : ComponentWrapper
134142
return _debugVersions;
135143
}
136144

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+
137156
private:
138157

139158
string[] _importPaths, _stringImportPaths, _importFiles, _versions, _debugVersions;
159+
CompileCommand[string] _compileCommands;
140160
}
141161

142-
private struct CompileCommand
162+
public struct CompileCommand
143163
{
144164
string directory;
145165
string file;
146166
string[] args;
147167
string output;
148168

149-
static CompileCommand fromJson(JSONValue json)
169+
private static CompileCommand fromJson(JSONValue json)
150170
{
151171
import std.algorithm : map;
152172
import std.array : array;
153173

154174
CompileCommand cc;
155175

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;
158180

159181
if (auto args = "arguments" in json)
160182
{
@@ -189,71 +211,101 @@ private struct CompileCommand
189211
return true;
190212
}
191213

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+
}
208217

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+
}
214221

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-
versions.put(arg[dmdVersionMark.length .. $]);
235-
break;
236-
case 5:
237-
versions.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();
249225
}
250226

251-
string getPath(string filename)
227+
string getPath(string filename) const
252228
{
253229
import std.path : absolutePath;
254230

255231
return absolutePath(filename, directory);
256232
}
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+
versions.put(arg[dmdVersionMark.length .. $]);
295+
break;
296+
case 5:
297+
versions.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+
}
257309
}
258310

259311
private string[] unescapeCommand(string cmd)

0 commit comments

Comments
 (0)