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.analyze.raw_config;
11 
12 import logger = std.experimental.logger;
13 
14 /** Handle parsing of user arguments.
15 
16 For a simple plugin this is overly complex. But a plugin very seldom stays
17 simple. By keeping the user input parsing and validation separate from the rest
18 of the program it become more robust to future changes.
19 */
20 struct RawConfiguration {
21     import std.getopt : GetoptResult, getopt, defaultGetoptPrinter;
22 
23     bool help;
24     bool errorHelp;
25     bool shortPluginHelp;
26     bool mccabe;
27     bool outputJson;
28     bool outputStdout;
29     int mccabeThreshold = 5;
30     int workerThreads = -1;
31     string outdir = ".";
32     string restrictDir = ".";
33     string[] cflags;
34     string[] compileDb;
35     string[] files;
36 
37     private GetoptResult help_info;
38 
39     void parse(string[] args) @safe {
40         static import std.getopt;
41 
42         try {
43             // getopt is safe in newer versions than 2.071.1
44             // remove this trusted wrapper there.
45             // dfmt off
46             () @trusted {
47             help_info = getopt(args, std.getopt.config.keepEndOfOptions,
48                    "short-plugin-help", "short description of the plugin",  &shortPluginHelp,
49                    "threads", "number of worker threads to use (default: detected CPU cores)", &workerThreads,
50                    "compile-db", "Retrieve compilation parameters from the file", &compileDb,
51                    "output-json", "Write the analyze result to json file(s)", &outputJson,
52                    "output-stdout", "Write the analyze result to stdout", &outputStdout,
53                    "restrict", "Restrict analyze of files to those in this directory tree (default: .)", &restrictDir,
54                    "mccabe", "Calculate the McCabe complexity of functions and files", &mccabe,
55                    "mccabe-threshold", "Threshold that must be reached for the McCabe value to be reported (default: 5)", &mccabeThreshold,
56                    "out", "directory to write result files to (default: .)", &outdir,
57                    "in", "Input file to parse", &files,
58                    );
59             }();
60             // dfmt on
61             help = help_info.helpWanted;
62         } catch (std.getopt.GetOptException ex) {
63             logger.error(ex.msg);
64             errorHelp = true;
65         }
66 
67         import std.algorithm : find;
68         import std.array : array;
69         import std.range : drop;
70 
71         // at this point args contain "what is left". What is interesting then is those after "--".
72         cflags = args.find("--").drop(1).array();
73 
74         if (!shortPluginHelp) {
75             // DMD-2.075.0
76             // workaround because the log is funky. those from
77             // application.plugin.toPlugin aren't "flushed". It think it is
78             // because pipeProcess uses linux pipes and this somehow interacts
79             // badly with std.experimental.logger;
80             debug logger.trace("");
81 
82             debug logger.trace(this);
83         }
84     }
85 
86     void printHelp() @trusted {
87         import std.stdio : writeln;
88 
89         defaultGetoptPrinter("Usage: dextool analyze [options] [--in=] [-- CFLAGS...]",
90                 help_info.options);
91     }
92 }