1 /**
2 Copyright: Copyright (c) 2017, Joakim Brännström. All rights reserved.
3 License: MPL-2
4 Author: Joakim Brännström (joakim.brannstrom@gmx.com)
5 
6 This Source Code Form is subject to the terms of the Mozilla Public License,
7 v.2.0. If a copy of the MPL was not distributed with this file, You can obtain
8 one at http://mozilla.org/MPL/2.0/.
9 */
10 module dextool.plugin.compiledb.frontend;
11 
12 import std.algorithm : joiner;
13 import std.array : array;
14 import std.exception;
15 
16 import logger = std.experimental.logger;
17 
18 import dextool.compilation_db : CompileCommandDB, CompileCommandFilter,
19     defaultCompilerFilter, parseFlag, fromArgCompileDb, toString;
20 import dextool.type : AbsolutePath, ExitStatusType, FileName;
21 
22 ExitStatusType doCompileDb(T)(ref T args) /*nothrow*/ {
23     CompileCommandDB compile_db;
24     try {
25         compile_db = args.inCompileDb.fromArgCompileDb;
26     }
27     catch (ErrnoException ex) {
28         logger.error(ex.msg);
29         return ExitStatusType.Errors;
30     }
31 
32     debug logger.trace(compile_db.toString);
33 
34     auto out_db = makeOutputFilename(args.out_);
35     writeDb(compile_db, out_db);
36 
37     return ExitStatusType.Ok;
38 }
39 
40 AbsolutePath makeOutputFilename(string out_) {
41     import std.file : isDir, FileException;
42     import std.path : buildPath;
43 
44     try {
45         if (out_.isDir) {
46             return AbsolutePath(FileName(buildPath(out_, "compile_commands.json")));
47         }
48     }
49     catch (FileException ex) {
50     }
51 
52     return AbsolutePath(FileName(out_));
53 }
54 
55 void writeDb(ref CompileCommandDB db, AbsolutePath dst) {
56     import std.stdio : File;
57 
58     auto fout = File(dst, "w");
59 
60     auto flag_filter = CompileCommandFilter(defaultCompilerFilter.filter.dup, 0);
61     logger.trace(flag_filter);
62 
63     void writeEntry(T)(ref const T e) {
64         import std.exception : assumeUnique;
65         import std.json : JSONValue;
66         import std.utf : byChar;
67 
68         string raw_flags = assumeUnique(e.parseFlag(flag_filter).flags.joiner(" ").byChar.array());
69 
70         fout.writefln(`  "directory": "%s",`, cast(string) e.directory);
71 
72         if (e.arguments.hasValue) {
73             fout.writefln(`  "command": "g++ %s",`, raw_flags);
74             fout.writefln(`  "arguments": "%s",`, raw_flags);
75         } else {
76             fout.writefln(`  "command": "%s",`, raw_flags);
77         }
78 
79         if (e.output.hasValue)
80             fout.writefln(`  "output": "%s",`, cast(string) e.absoluteOutput);
81         fout.writefln(`  "file": "%s"`, cast(string) e.absoluteFile);
82     }
83 
84     if (db.length == 0) {
85         return;
86     }
87 
88     fout.writeln("[");
89 
90     foreach (ref const e; db[0 .. $ - 1]) {
91         fout.writeln(" {");
92         writeEntry(e);
93         fout.writeln(" },");
94     }
95 
96     fout.writeln(" {");
97     writeEntry(db[$ - 1]);
98     fout.writeln(" }");
99 
100     fout.writeln("]");
101 }